KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > gui2 > MainFrame


1 /*
2  * FindBugs - Find Bugs in Java programs
3  * Copyright (C) 2006, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA
18  */

19
20 package edu.umd.cs.findbugs.gui2;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Button JavaDoc;
24 import java.awt.Color JavaDoc;
25 import java.awt.Component JavaDoc;
26 import java.awt.Container JavaDoc;
27 import java.awt.Cursor JavaDoc;
28 import java.awt.Dimension JavaDoc;
29 import java.awt.Event JavaDoc;
30 import java.awt.Font JavaDoc;
31 import java.awt.GridBagConstraints JavaDoc;
32 import java.awt.GridBagLayout JavaDoc;
33 import java.awt.GridLayout JavaDoc;
34 import java.awt.Insets JavaDoc;
35 import java.awt.Toolkit JavaDoc;
36 import java.awt.event.ActionEvent JavaDoc;
37 import java.awt.event.ActionListener JavaDoc;
38 import java.awt.event.ComponentAdapter JavaDoc;
39 import java.awt.event.ComponentEvent JavaDoc;
40 import java.awt.event.KeyEvent JavaDoc;
41 import java.awt.event.MouseAdapter JavaDoc;
42 import java.awt.event.MouseEvent JavaDoc;
43 import java.awt.event.MouseListener JavaDoc;
44 import java.awt.event.WindowAdapter JavaDoc;
45 import java.awt.event.WindowEvent JavaDoc;
46 import java.io.File JavaDoc;
47 import java.io.FileInputStream JavaDoc;
48 import java.io.FileNotFoundException JavaDoc;
49 import java.io.FileOutputStream JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.lang.reflect.Method JavaDoc;
53 import java.net.MalformedURLException JavaDoc;
54 import java.net.URL JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.Iterator JavaDoc;
57 import java.util.zip.GZIPInputStream JavaDoc;
58
59 import javax.swing.Action JavaDoc;
60 import javax.swing.ActionMap JavaDoc;
61 import javax.swing.BorderFactory JavaDoc;
62 import javax.swing.Box JavaDoc;
63 import javax.swing.ImageIcon JavaDoc;
64 import javax.swing.JButton JavaDoc;
65 import javax.swing.JButton JavaDoc;
66 import javax.swing.JEditorPane JavaDoc;
67 import javax.swing.JFileChooser JavaDoc;
68 import javax.swing.JFrame JavaDoc;
69 import javax.swing.JLabel JavaDoc;
70 import javax.swing.JMenu JavaDoc;
71 import javax.swing.JMenuBar JavaDoc;
72 import javax.swing.JMenuItem JavaDoc;
73 import javax.swing.JOptionPane JavaDoc;
74 import javax.swing.JPanel JavaDoc;
75 import javax.swing.JPopupMenu JavaDoc;
76 import javax.swing.JScrollPane JavaDoc;
77 import javax.swing.JSplitPane JavaDoc;
78 import javax.swing.JTextArea JavaDoc;
79 import javax.swing.JTextField JavaDoc;
80 import javax.swing.JTextPane JavaDoc;
81 import javax.swing.JTree JavaDoc;
82 import javax.swing.KeyStroke JavaDoc;
83 import javax.swing.SwingUtilities JavaDoc;
84 import javax.swing.border.BevelBorder JavaDoc;
85 import javax.swing.event.TreeSelectionEvent JavaDoc;
86 import javax.swing.event.TreeSelectionListener JavaDoc;
87 import javax.swing.plaf.basic.BasicTreeUI JavaDoc;
88 import javax.swing.table.JTableHeader JavaDoc;
89 import javax.swing.text.JTextComponent JavaDoc;
90 import javax.swing.text.TextAction JavaDoc;
91 import javax.swing.text.html.HTMLEditorKit JavaDoc;
92 import javax.swing.text.html.StyleSheet JavaDoc;
93 import javax.swing.tree.TreePath JavaDoc;
94 import javax.swing.tree.TreeSelectionModel JavaDoc;
95
96 import edu.umd.cs.findbugs.BugAnnotation;
97 import edu.umd.cs.findbugs.BugInstance;
98 import edu.umd.cs.findbugs.ClassAnnotation;
99 import edu.umd.cs.findbugs.FieldAnnotation;
100 import edu.umd.cs.findbugs.I18N;
101 import edu.umd.cs.findbugs.MethodAnnotation;
102 import edu.umd.cs.findbugs.PackageMemberAnnotation;
103 import edu.umd.cs.findbugs.Project;
104 import edu.umd.cs.findbugs.SourceLineAnnotation;
105 import edu.umd.cs.findbugs.SystemProperties;
106 import edu.umd.cs.findbugs.annotations.NonNull;
107 import edu.umd.cs.findbugs.ba.SourceFinder;
108 import edu.umd.cs.findbugs.gui.ConsoleLogger;
109 import edu.umd.cs.findbugs.gui.LogSync;
110 import edu.umd.cs.findbugs.gui.Logger;
111 import edu.umd.cs.findbugs.gui2.BugTreeModel.PleaseWaitTreeModel;
112 import edu.umd.cs.findbugs.sourceViewer.NavigableTextPane;
113
114 @SuppressWarnings JavaDoc("serial")
115
116 /*
117  * This is where it all happens... seriously... all of it...
118  * All the menus are set up, all the listeners, all the frames, dockable window functionality
119  * There is no one style used, no one naming convention, its all just kinda here. This is another one of those
120  * classes where no one knows quite why it works.
121  */

122 /**
123  * The MainFrame is just that, the main application window where just about everything happens.
124  */

125 public class MainFrame extends FBFrame implements LogSync
126 {
127     static JButton JavaDoc newButton(String JavaDoc key, String JavaDoc name) {
128         JButton JavaDoc b = new JButton JavaDoc();
129         edu.umd.cs.findbugs.L10N.localiseButton(b, key, name, false);
130         return b;
131     }
132     static JMenuItem JavaDoc newJMenuItem(String JavaDoc key, String JavaDoc string, int vkF) {
133         JMenuItem JavaDoc m = new JMenuItem JavaDoc();
134         edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, false);
135         m.setMnemonic(vkF);
136         return m;
137
138     }
139     static JMenuItem JavaDoc newJMenuItem(String JavaDoc key, String JavaDoc string) {
140         JMenuItem JavaDoc m = new JMenuItem JavaDoc();
141         edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true);
142         return m;
143
144     }
145     static JMenu JavaDoc newJMenu(String JavaDoc key, String JavaDoc string) {
146         JMenu JavaDoc m = new JMenu JavaDoc();
147         edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true);
148         return m;
149     }
150     JTree JavaDoc tree;
151     private BasicTreeUI JavaDoc treeUI;
152     boolean userInputEnabled;
153         
154     static final String JavaDoc DEFAULT_SOURCE_CODE_MSG = edu.umd.cs.findbugs.L10N.getLocalString("msg.nosource_txt", "No available source");
155     
156     static final int COMMENTS_TAB_STRUT_SIZE = 5;
157     static final int COMMENTS_MARGIN = 5;
158     static final int SEARCH_TEXT_FIELD_SIZE = 32;
159     
160     private JTextField JavaDoc sourceSearchTextField = new JTextField JavaDoc(SEARCH_TEXT_FIELD_SIZE);
161     private JButton JavaDoc findButton = newButton("button.find", "Find");
162     private JButton JavaDoc findNextButton = newButton("button.findNext", "Find Next");
163     private JButton JavaDoc findPreviousButton = newButton("button.findPrev", "Find Previous");
164
165     public static final boolean DEBUG = SystemProperties.getBoolean("gui2.debug");
166     
167     private static final boolean MAC_OS_X = SystemProperties.getProperty("os.name").toLowerCase().startsWith("mac os x");
168     final static String JavaDoc WINDOW_MODIFIED = "windowModified";
169
170     NavigableTextPane sourceCodeTextPane = new NavigableTextPane();
171     private JScrollPane JavaDoc sourceCodeScrollPane;
172     
173     final CommentsArea comments;
174     private SorterTableColumnModel sorter;
175     private JTableHeader JavaDoc tableheader;
176     private JLabel JavaDoc statusBarLabel = new JLabel JavaDoc();
177     
178     private JPanel JavaDoc summaryTopPanel;
179     private final HTMLEditorKit JavaDoc htmlEditorKit = new HTMLEditorKit JavaDoc();
180     private final JEditorPane JavaDoc summaryHtmlArea = new JEditorPane JavaDoc();
181     private JScrollPane JavaDoc summaryHtmlScrollPane = new JScrollPane JavaDoc(summaryHtmlArea);
182     
183
184     final private FindBugsLayoutManagerFactory findBugsLayoutManagerFactory;
185     final private FindBugsLayoutManager guiLayout;
186     
187     /* To change this method must use setProjectChanged(boolean b).
188      * This is because saveProjectItemMenu is dependent on it for when
189      * saveProjectMenuItem should be enabled.
190      */

191     boolean projectChanged = false;
192     final private JMenuItem JavaDoc editProjectMenuItem = newJMenuItem("menu.addRemoveFiles", "Add/Remove Files...", KeyEvent.VK_F);
193     final private JMenuItem JavaDoc saveProjectMenuItem = newJMenuItem("menu.save_item", "Save Project", KeyEvent.VK_S);
194     BugLeafNode currentSelectedBugLeaf;
195     BugAspects currentSelectedBugAspects;
196     private JPopupMenu JavaDoc bugPopupMenu;
197     private JPopupMenu JavaDoc branchPopupMenu;
198     private static MainFrame instance;
199     private JMenu JavaDoc recentProjectsMenu;
200     private JMenuItem JavaDoc preferencesMenuItem;
201     private File JavaDoc projectDirectory;
202     private Project curProject;
203     private JScrollPane JavaDoc treeScrollPane;
204     SourceFinder sourceFinder;
205     private Object JavaDoc lock = new Object JavaDoc();
206     private boolean newProject = false;
207
208     private Logger logger = new ConsoleLogger(this);
209     SourceCodeDisplay displayer = new SourceCodeDisplay(this);
210     
211     static void makeInstance(FindBugsLayoutManagerFactory factory) {
212         if (instance != null) throw new IllegalStateException JavaDoc();
213         instance=new MainFrame(factory);
214         instance.initializeGUI();
215     }
216     /**
217      * @param string
218      * @param vkF
219      * @return
220      */

221
222     static MainFrame getInstance() {
223         if (instance==null) throw new IllegalStateException JavaDoc();
224         return instance;
225     }
226     
227     
228     private void initializeGUI() {
229         SwingUtilities.invokeLater(new InitializeGUI());
230     }
231     private MainFrame(FindBugsLayoutManagerFactory factory)
232     {
233         this.findBugsLayoutManagerFactory = factory;
234         this.guiLayout = factory.getInstance(this);
235         this.comments = new CommentsArea(this);
236     }
237     
238     /**
239      * Show About
240      */

241     void about() {
242         AboutDialog dialog = new AboutDialog(this, logger, true);
243         dialog.setSize(600, 554);
244         dialog.setLocationRelativeTo(this);
245         dialog.setVisible(true);
246     }
247     
248     /**
249      * This method is called when the application is closing. This is either by
250      * the exit menuItem or by clicking on the window's system menu.
251      */

252     void callOnClose(){
253         comments.saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
254         if(projectChanged){
255             int value = JOptionPane.showConfirmDialog(MainFrame.this, edu.umd.cs.findbugs.L10N.getLocalString("msg.you_are_closing_txt", "You are closing") + " " +
256                     edu.umd.cs.findbugs.L10N.getLocalString("msg.without_saving_txt", "without saving. Do you want to save?"),
257                     edu.umd.cs.findbugs.L10N.getLocalString("msg.confirm_save_txt", "Do you want to save?"), JOptionPane.YES_NO_CANCEL_OPTION,
258                     JOptionPane.QUESTION_MESSAGE);
259             
260             if(value == JOptionPane.CANCEL_OPTION || value == JOptionPane.CLOSED_OPTION)
261                 return ;
262             else if(value == JOptionPane.YES_OPTION){
263                 if(projectDirectory == null){
264                     if(!projectSaveAs())
265                         return ;
266                 }
267                 else
268                     save(projectDirectory);
269             }
270         }
271
272         GUISaveState.getInstance().setPreviousComments(comments.prevCommentsList);
273         guiLayout.saveState();
274         GUISaveState.getInstance().setFrameBounds( getBounds() );
275         GUISaveState.getInstance().save();
276         
277         System.exit(0);
278     }
279
280     private void createRecentProjectsMenu(){
281         for (File JavaDoc p: GUISaveState.getInstance().getRecentProjects())
282         {
283             addRecentProjectToMenu(p);
284         }
285     }
286     
287     private void addRecentProjectToMenu(final File JavaDoc f)
288     {
289         if (!f.exists())
290         {
291             if (MainFrame.DEBUG) System.err.println("a recent project was not found, removing it from menu");
292             return;
293         }
294         final JMenuItem JavaDoc item=new JMenuItem JavaDoc(f.getName().substring(0,f.getName().length()-4));
295         item.addActionListener(new ActionListener JavaDoc(){
296             public void actionPerformed(ActionEvent JavaDoc e)
297             {
298                 try
299                 {
300                     setCursor(new Cursor JavaDoc(Cursor.WAIT_CURSOR));
301
302                     if (!f.exists())
303                     {
304                         JOptionPane.showMessageDialog(null,edu.umd.cs.findbugs.L10N.getLocalString("msg.proj_not_found", "This project can no longer be found"));
305                         GUISaveState.getInstance().projectNotFound(f);
306                         return;
307                     }
308                     GUISaveState.getInstance().projectReused(f);//Move to front in GUISaveState, so it will be last thing to be removed from the list
309
//Move to front of recent projects menu, so GUISaveState matches with the project menu seen by the user
310
boolean exists=false;
311                     for (int x=0; x< recentProjectsMenu.getItemCount(); x++)
312                     {
313                         if (item.getText().equalsIgnoreCase(recentProjectsMenu.getItem(x).getText()))
314                         {
315                             exists=true;
316                             recentProjectsMenu.remove(x);
317                             recentProjectsMenu.insert(item, 0);//Move to front
318
}
319                     }
320                     if (!exists)
321                         throw new IllegalStateException JavaDoc ("User used a recent projects menu item that didn't exist.");
322                     
323                     projectDirectory=f.getParentFile();
324                     File JavaDoc fasFile=new File JavaDoc(projectDirectory.getAbsolutePath() + File.separator + projectDirectory.getName() + ".fas");
325                     try
326                     {
327                         ProjectSettings.loadInstance(new FileInputStream JavaDoc(fasFile));
328                     } catch (FileNotFoundException JavaDoc exception)
329                     {
330                         //Silently make a new instance
331
ProjectSettings.newInstance();
332                     }
333                     
334                     final File JavaDoc extraFinalReferenceToXmlFile=f;
335                     new Thread JavaDoc(new Runnable JavaDoc(){
336                         public void run()
337                         {
338                             updateDesignationDisplay();
339                             if (curProject != null && projectChanged)
340                             {
341                                 int response = JOptionPane.showConfirmDialog(MainFrame.this,
342                                         edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_current_changes", "The current project has been changed, Save current changes?")
343                                         ,edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_changes", "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
344
345                                 if (response == JOptionPane.YES_OPTION)
346                                 {
347                                     if (projectDirectory!=null)
348                                         save(projectDirectory);
349                                     else
350                                         projectSaveAs();
351                                 }
352                                 else if (response == JOptionPane.CANCEL_OPTION)
353                                     return;
354                                 //IF no, do nothing.
355
}
356                             BugTreeModel model=(BugTreeModel)tree.getModel();
357 // Debug.println("please wait called by open menu item");
358
BugTreeModel.pleaseWait();
359                             MainFrame.this.setRebuilding(true);
360                             Project newProject = new Project();
361                             BugSet bs=BugLoader.loadBugs(newProject, extraFinalReferenceToXmlFile);
362                             MainFrame.this.setRebuilding(false);
363                             if (bs!=null)
364                             {
365                                 displayer.clearCache();
366                                 model.getOffListenerList();
367                                 model.changeSet(bs);
368                                 curProject=newProject;
369                                 MainFrame.getInstance().updateStatusBar();
370                                 MainFrame.this.setTitle("FindBugs: " + curProject.getProjectFileName());
371                             }
372                             
373                             
374                             
375                             setProjectChanged(false);
376                             editProjectMenuItem.setEnabled(true);
377                             clearSourcePane();
378                         }
379                     }).start();
380                 }
381                 finally
382                 {
383                     setCursor(new Cursor JavaDoc(Cursor.DEFAULT_CURSOR));
384                 }
385             }
386         });
387         item.setFont(item.getFont().deriveFont(Driver.getFontSize()));
388         
389         boolean exists=false;
390         for (int x=0; x< recentProjectsMenu.getItemCount(); x++)
391         {
392             if (item.getText().equalsIgnoreCase(recentProjectsMenu.getItem(x).getText()))
393             {
394                 exists=true;
395                 recentProjectsMenu.remove(x);
396                 recentProjectsMenu.insert(item, 0);//Move to front
397
}
398         }
399         if (!exists)
400             recentProjectsMenu.insert(item,0);
401     }
402
403     /**
404      * Creates popup menu for bugs on tree.
405      * @return
406      */

407     private JPopupMenu JavaDoc createBugPopupMenu() {
408         JPopupMenu JavaDoc popupMenu = new JPopupMenu JavaDoc();
409         
410         JMenuItem JavaDoc suppressMenuItem = newJMenuItem("menu.suppress", "Suppress this bug");
411         
412         suppressMenuItem.addActionListener(new ActionListener JavaDoc(){
413             public void actionPerformed(ActionEvent JavaDoc evt){
414                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
415                 //This MUST be done in this order:
416
//getIndexOfChild relies on the fact that things have not yet been removed from the tree!
417
TreePath JavaDoc path=tree.getSelectionPath();
418                 FilterMatcher.notifyListeners(FilterListener.SUPPRESSING, path);
419                 ProjectSettings.getInstance().getSuppressionMatcher().add(currentSelectedBugLeaf.getBug());
420                 PreferencesFrame.getInstance().suppressionsChanged(currentSelectedBugLeaf);
421                 ((BugTreeModel)(tree.getModel())).resetData();//Necessary to keep suppressions from getting out of sync with tree.
422
clearSourcePane();
423                 updateStatusBar();
424                 
425                 setProjectChanged(true);
426             }
427             
428         });
429         
430         popupMenu.add(suppressMenuItem);
431         
432         JMenuItem JavaDoc filterMenuItem = newJMenuItem("menu.filterBugsLikeThis", "Filter bugs like this");
433         
434         filterMenuItem.addActionListener(new ActionListener JavaDoc(){
435             public void actionPerformed(ActionEvent JavaDoc evt){
436                 new NewFilterFromBug(currentSelectedBugLeaf.getBug());
437                 
438                 setProjectChanged(true);
439             }
440         });
441         
442         popupMenu.add(filterMenuItem);
443         
444         JMenu JavaDoc changeDesignationMenu = newJMenu("menu.changeDesignation", "Change bug designation");
445         
446         int i = 0;
447         int keyEvents [] = {KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5, KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9};
448         for(String JavaDoc key : I18N.instance().getUserDesignationKeys(true)) {
449             String JavaDoc name = I18N.instance().getUserDesignation(key);
450             comments.addDesignationItem(changeDesignationMenu, name, keyEvents[i++]);
451         }
452         
453         popupMenu.add(changeDesignationMenu);
454         
455         return popupMenu;
456     }
457     
458     /**
459      * Creates the branch pop up menu that ask if the user wants
460      * to hide all the bugs in that branch.
461      * @return
462      */

463     private JPopupMenu JavaDoc createBranchPopUpMenu(){
464         JPopupMenu JavaDoc popupMenu = new JPopupMenu JavaDoc();
465         
466         JMenuItem JavaDoc filterMenuItem = newJMenuItem("menu.filterTheseBugs", "Filter these bugs");
467         
468         filterMenuItem.addActionListener(new ActionListener JavaDoc()
469         {
470             public void actionPerformed(ActionEvent JavaDoc evt)
471             {
472                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
473                 
474                 StackedFilterMatcher sfm = currentSelectedBugAspects.getStackedFilterMatcher();
475                 if (!ProjectSettings.getInstance().getAllMatchers().contains(sfm))
476                     ProjectSettings.getInstance().addFilter(sfm);
477                 
478                 setProjectChanged(true);
479             }
480         });
481         
482         popupMenu.add(filterMenuItem);
483         
484         JMenu JavaDoc changeDesignationMenu = newJMenu("menu.changeDesignation", "Change bug designation");
485         
486         int i = 0;
487         int keyEvents [] = {KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5, KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9};
488         for(String JavaDoc key : I18N.instance().getUserDesignationKeys(true)) {
489             String JavaDoc name = I18N.instance().getUserDesignation(key);
490             addDesignationItem(changeDesignationMenu, name, keyEvents[i++]);
491         }
492         
493         popupMenu.add(changeDesignationMenu);
494         
495         return popupMenu;
496     }
497
498     /**
499      * Creates the MainFrame's menu bar.
500      * @return the menu bar for the MainFrame
501      */

502     protected JMenuBar JavaDoc createMainMenuBar() {
503         JMenuBar JavaDoc menuBar = new JMenuBar JavaDoc();
504         
505         //Create JMenus for menuBar.
506
JMenu JavaDoc fileMenu = newJMenu("menu.file_menu", "File");
507         fileMenu.setMnemonic(KeyEvent.VK_F);
508         JMenu JavaDoc editMenu = newJMenu("menu.edit_menu", "Edit");
509         editMenu.setMnemonic(KeyEvent.VK_E);
510         
511         //Edit fileMenu JMenu object.
512
JMenuItem JavaDoc newProjectMenuItem = newJMenuItem("menu.new_item", "New Project", KeyEvent.VK_N);
513         JMenuItem JavaDoc openProjectMenuItem = newJMenuItem("menu.open_item", "Open Project...", KeyEvent.VK_O);
514         recentProjectsMenu = newJMenu("menu.recent_menu", "menu.recent_menu");
515         recentProjectsMenu.setMnemonic(KeyEvent.VK_E);
516         createRecentProjectsMenu();
517         JMenuItem JavaDoc saveAsProjectMenuItem = newJMenuItem("menu.saveas_item", "Save Project As...", KeyEvent.VK_A);
518         JMenuItem JavaDoc importBugsMenuItem = newJMenuItem("menu.loadbugs_item", "Load Analysis...", KeyEvent.VK_L);
519         JMenuItem JavaDoc exportBugsMenuItem = newJMenuItem("menu.savebugs_item", "Save Analysis...", KeyEvent.VK_B);
520         JMenuItem JavaDoc redoAnalysis = newJMenuItem("menu.rerunAnalysis", "Redo Analysis", KeyEvent.VK_R);
521         JMenuItem JavaDoc mergeMenuItem = newJMenuItem("menu.mergeAnalysis", "Merge Analysis...");
522         
523         JMenuItem JavaDoc exitMenuItem = null;
524         if (!MAC_OS_X) {
525             exitMenuItem = newJMenuItem("menu.exit", "Exit", KeyEvent.VK_X);
526             exitMenuItem.addActionListener(new ActionListener JavaDoc(){
527             public void actionPerformed(ActionEvent JavaDoc evt){
528                 callOnClose();
529             }
530             });
531         }
532         JMenu JavaDoc windowMenu = guiLayout.createWindowMenu();
533
534         
535         attachAccelaratorKey(newProjectMenuItem, KeyEvent.VK_N);
536         
537         newProjectMenuItem.addActionListener(new ActionListener JavaDoc(){
538             public void actionPerformed(ActionEvent JavaDoc evt){
539                 newProjectMenu();
540             }
541         });
542         
543         attachAccelaratorKey(editProjectMenuItem, KeyEvent.VK_F);
544         editProjectMenuItem.addActionListener(new ActionListener JavaDoc()
545         {
546             public void actionPerformed(ActionEvent JavaDoc evt)
547             {
548                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
549                 new NewProjectWizard(curProject);
550             }
551         });
552         
553         openProjectMenuItem.setEnabled(true);
554         attachAccelaratorKey(openProjectMenuItem, KeyEvent.VK_O);
555         openProjectMenuItem.addActionListener(new ActionListener JavaDoc(){
556             public void actionPerformed(ActionEvent JavaDoc evt){
557                 openProject();
558             }
559         });
560
561         mergeMenuItem.setEnabled(true);
562         mergeMenuItem.addActionListener(new ActionListener JavaDoc(){
563             public void actionPerformed(ActionEvent JavaDoc evt){
564                 mergeAnalysis();
565             }
566         });
567         
568         redoAnalysis.setEnabled(true);
569         attachAccelaratorKey(redoAnalysis, KeyEvent.VK_R);
570         redoAnalysis.addActionListener(new ActionListener JavaDoc(){
571             public void actionPerformed(ActionEvent JavaDoc evt){
572                 redoAnalysis();
573             }
574         });
575         
576         saveProjectMenuItem.setEnabled(false);
577         attachAccelaratorKey(saveProjectMenuItem, KeyEvent.VK_S);
578         saveProjectMenuItem.addActionListener(new ActionListener JavaDoc(){
579             public void actionPerformed(ActionEvent JavaDoc evt){
580                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
581                 
582                 save(projectDirectory);
583             }
584         });
585         
586         saveAsProjectMenuItem.setEnabled(true);
587         attachAccelaratorKey(saveAsProjectMenuItem, KeyEvent.VK_S, Event.SHIFT_MASK);
588         saveAsProjectMenuItem.addActionListener(new ActionListener JavaDoc(){
589             public void actionPerformed(ActionEvent JavaDoc evt){
590                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
591                 
592                 if(projectSaveAs())
593                     saveProjectMenuItem.setEnabled(true);
594             }
595         });
596         
597         attachAccelaratorKey(importBugsMenuItem, KeyEvent.VK_O, Event.ALT_MASK);
598         importBugsMenuItem.addActionListener(new ActionListener JavaDoc(){
599             public void actionPerformed(ActionEvent JavaDoc evt){
600                 loadAnalysis();
601             }
602         });
603         
604         exportBugsMenuItem.setEnabled(true);
605         attachAccelaratorKey(exportBugsMenuItem, KeyEvent.VK_S, Event.ALT_MASK);
606         exportBugsMenuItem.addActionListener(new ActionListener JavaDoc(){
607             public void actionPerformed(ActionEvent JavaDoc evt){
608                 saveAnalysis();
609             }
610         });
611
612         
613                 
614         fileMenu.add(newProjectMenuItem);
615         fileMenu.add(editProjectMenuItem);
616         fileMenu.addSeparator();
617         fileMenu.add(openProjectMenuItem);
618         fileMenu.add(recentProjectsMenu);
619         fileMenu.addSeparator();
620         fileMenu.add(saveProjectMenuItem);
621         fileMenu.add(saveAsProjectMenuItem);
622         fileMenu.addSeparator();
623         fileMenu.add(importBugsMenuItem);
624         fileMenu.add(exportBugsMenuItem);
625         fileMenu.addSeparator();
626         fileMenu.add(redoAnalysis);
627         fileMenu.add(mergeMenuItem);
628         if (exitMenuItem != null) {
629             fileMenu.addSeparator();
630             fileMenu.add(exitMenuItem);
631         }
632                 
633         menuBar.add(fileMenu);
634         
635         //Edit editMenu Menu object.
636
JMenuItem JavaDoc cutMenuItem = new JMenuItem JavaDoc(new CutAction());
637         JMenuItem JavaDoc copyMenuItem = new JMenuItem JavaDoc(new CopyAction());
638         JMenuItem JavaDoc pasteMenuItem = new JMenuItem JavaDoc(new PasteAction());
639         preferencesMenuItem = newJMenuItem("menu.filtersAndSupressions", "Filters/Suppressions...");
640         JMenuItem JavaDoc sortMenuItem = newJMenuItem("menu.sortConfiguration", "Sort Configuration...");
641         JMenuItem JavaDoc goToLineMenuItem = newJMenuItem("menu.gotoLine", "Go to line...");
642         
643         attachAccelaratorKey(cutMenuItem, KeyEvent.VK_X);
644         attachAccelaratorKey(copyMenuItem, KeyEvent.VK_C);
645         attachAccelaratorKey(pasteMenuItem, KeyEvent.VK_V);
646         
647         preferencesMenuItem.addActionListener(new ActionListener JavaDoc(){
648             public void actionPerformed(ActionEvent JavaDoc evt){
649                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
650                 PreferencesFrame.getInstance().setLocationRelativeTo(MainFrame.this);
651                 PreferencesFrame.getInstance().setVisible(true);
652             }
653         });
654         
655         sortMenuItem.addActionListener(new ActionListener JavaDoc(){
656             public void actionPerformed(ActionEvent JavaDoc evt){
657                 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
658                 SorterDialog.getInstance().setLocationRelativeTo(MainFrame.this);
659                 SorterDialog.getInstance().setVisible(true);
660             }
661         });
662         
663         attachAccelaratorKey(goToLineMenuItem, KeyEvent.VK_L);
664         goToLineMenuItem.addActionListener(new ActionListener JavaDoc(){
665             public void actionPerformed(ActionEvent JavaDoc evt){
666                 guiLayout.makeSourceVisible();
667                 try{
668                     int num = Integer.parseInt(JOptionPane.showInputDialog(MainFrame.this, "", edu.umd.cs.findbugs.L10N.getLocalString("dlg.go_to_line_lbl", "Go To Line") + ":", JOptionPane.QUESTION_MESSAGE));
669                     displayer.showLine(num);
670                 }
671                 catch(NumberFormatException JavaDoc e){}
672             }});
673         
674         editMenu.add(cutMenuItem);
675         editMenu.add(copyMenuItem);
676         editMenu.add(pasteMenuItem);
677         editMenu.addSeparator();
678         editMenu.add(goToLineMenuItem);
679         editMenu.addSeparator();
680         //editMenu.add(selectAllMenuItem);
681
// editMenu.addSeparator();
682
editMenu.add(preferencesMenuItem);
683         editMenu.add(sortMenuItem);
684         
685         menuBar.add(editMenu);
686         
687         if (windowMenu != null)
688             menuBar.add(windowMenu);
689         
690         final ActionMap JavaDoc map = tree.getActionMap();
691         
692         JMenu JavaDoc navMenu = newJMenu("menu.navigation", "Navigation");
693         
694         addNavItem(map, navMenu, "menu.expand", "Expand", "expand", KeyEvent.VK_RIGHT );
695         addNavItem(map, navMenu, "menu.collapse", "Collapse", "collapse", KeyEvent.VK_LEFT);
696         addNavItem(map, navMenu, "menu.up", "Up", "selectPrevious", KeyEvent.VK_UP );
697         addNavItem(map, navMenu, "menu.down", "Down", "selectNext", KeyEvent.VK_DOWN);
698                 
699         menuBar.add(navMenu);
700         
701         JMenu JavaDoc designationMenu = newJMenu("menu.designation", "Designation");
702         int i = 0;
703         int keyEvents [] = {KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5, KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9};
704         for(String JavaDoc key : I18N.instance().getUserDesignationKeys(true)) {
705             String JavaDoc name = I18N.instance().getUserDesignation(key);
706             addDesignationItem(designationMenu, name, keyEvents[i++]);
707         }
708         menuBar.add(designationMenu);
709
710         if (!MAC_OS_X) {
711             // On Mac, 'About' appears under Findbugs menu, so no need for it here
712
JMenu JavaDoc helpMenu = newJMenu("menu.help_menu", "Help");
713             JMenuItem JavaDoc aboutItem = newJMenuItem("menu.about_item", "About FindBugs");
714             helpMenu.add(aboutItem);
715
716                 aboutItem.addActionListener(new java.awt.event.ActionListener JavaDoc() {
717                         public void actionPerformed(java.awt.event.ActionEvent JavaDoc evt) {
718                             about();
719                         }
720                     });
721                 menuBar.add(helpMenu);
722         }
723         return menuBar;
724     }
725     /**
726      * @param map
727      * @param navMenu
728      */

729     private void addNavItem(final ActionMap JavaDoc map, JMenu JavaDoc navMenu, String JavaDoc menuNameKey, String JavaDoc menuNameDefault, String JavaDoc actionName, int keyEvent) {
730         JMenuItem JavaDoc toggleItem = newJMenuItem(menuNameKey, menuNameDefault);
731         toggleItem.addActionListener(treeActionAdapter(map, actionName));
732         attachAccelaratorKey(toggleItem, keyEvent);
733         navMenu.add(toggleItem);
734     }
735     ActionListener JavaDoc treeActionAdapter(ActionMap JavaDoc map, String JavaDoc actionName) {
736         final Action JavaDoc selectPrevious = map.get(actionName);
737         return new ActionListener JavaDoc() {
738             public void actionPerformed(ActionEvent JavaDoc e) {
739                 e.setSource(tree);
740                 selectPrevious.actionPerformed(e);
741             }};
742     }
743     static void attachAccelaratorKey(JMenuItem JavaDoc item, int keystroke) {
744         attachAccelaratorKey(item, keystroke, 0);
745     }
746     static void attachAccelaratorKey(JMenuItem JavaDoc item, int keystroke,
747                                                                      int additionalMask) {
748         // As far as I know, Mac is the only platform on which it is normal
749
// practice to use accelerator masks such as Shift and Alt, so
750
// if we're not running on Mac, just ignore them
751
if (!MAC_OS_X && additionalMask != 0) {
752             return;
753         }
754
755         item.setAccelerator(KeyStroke.getKeyStroke(keystroke,
756                                                                                              Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | additionalMask));
757     }
758     void newProject(){
759         setProjectChanged(true);
760         clearSourcePane();
761         
762         if(newProject){
763             setTitle("FindBugs: " + Project.UNNAMED_PROJECT);
764             projectDirectory = null;
765             saveProjectMenuItem.setEnabled(false);
766             editProjectMenuItem.setEnabled(true);
767         }
768     }
769
770     
771     /**
772      * Called when use has not previous saved project. Uses save() after finds
773      * where user want to save file.
774      * @return True if successful.
775      */

776     private boolean projectSaveAs(){
777         if (curProject==null)
778         {
779             JOptionPane.showMessageDialog(MainFrame.this,edu.umd.cs.findbugs.L10N.getLocalString("dlg.no_proj_save_lbl", "There is no project to save"));
780             return false;
781         }
782         
783         FBFileChooser jfc=new FBFileChooser();
784         jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
785         jfc.setFileFilter(new FindBugsProjectFileFilter());
786         jfc.setDialogTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.saveas_ttl", "Save as..."));
787
788         boolean exists = false;
789         File JavaDoc dir=null;
790         boolean retry;
791         do
792         {
793             retry = false;
794             int value=jfc.showSaveDialog(MainFrame.this);
795             if (value!=JFileChooser.APPROVE_OPTION) return false;
796
797             dir = jfc.getSelectedFile();
798             File JavaDoc xmlFile=new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".xml");
799             File JavaDoc fasFile=new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".fas");
800             exists=xmlFile.exists() && fasFile.exists();
801
802             if(exists){
803                 int response = JOptionPane.showConfirmDialog(jfc,
804                         edu.umd.cs.findbugs.L10N.getLocalString("dlg.proj_already_exists_lbl", "This project already exists.\nDo you want to replace it?"),
805                         edu.umd.cs.findbugs.L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
806
807                 if(response == JOptionPane.OK_OPTION)
808                     retry = false;
809                 if(response == JOptionPane.CANCEL_OPTION){
810                     retry = true;
811                     continue;
812                 }
813             }
814
815             boolean good=save(dir);
816             if (good==false)
817             {
818                 JOptionPane.showMessageDialog(MainFrame.this, edu.umd.cs.findbugs.L10N.getLocalString("dlg.saving_error_lbl", "An error occurred in saving."));
819                 return false;
820             }
821             projectDirectory=dir;
822
823         } while (retry);
824         curProject.setProjectFileName(projectDirectory.getName());
825         File JavaDoc xmlFile=new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".xml");
826
827         //If the file already existed, its already in the preferences, as well as the recent projects menu items, only add it if they change the name, otherwise everything we're storing is still accurate since all we're storing is the location of the file.
828
if (!exists)
829         {
830             GUISaveState.getInstance().addRecentProject(xmlFile);
831         }
832
833         MainFrame.this.addRecentProjectToMenu(xmlFile);
834
835         return true;
836     }
837     
838     /**
839      *
840      * @return
841      */

842     JPanel JavaDoc bugListPanel()
843     {
844         JPanel JavaDoc topPanel = new JPanel JavaDoc();
845         topPanel.setMinimumSize(new Dimension JavaDoc(200,200));
846         tableheader = new JTableHeader JavaDoc();
847         //Listener put here for when user double clicks on sorting
848
//column header SorterDialog appears.
849
tableheader.addMouseListener(new MouseAdapter JavaDoc(){
850
851             public void mouseClicked(MouseEvent JavaDoc e) {
852                 if (!tableheader.getReorderingAllowed())
853                     return;
854                 if (e.getClickCount()==2)
855                     SorterDialog.getInstance().setVisible(true);
856             }
857
858             public void mouseReleased(MouseEvent JavaDoc arg0) {
859                 if (!tableheader.getReorderingAllowed())
860                     return;
861                 BugTreeModel bt=(BugTreeModel) (MainFrame.this.getTree().getModel());
862                 bt.checkSorter();
863             }
864         });
865         sorter = GUISaveState.getInstance().getStarterTable();
866         tableheader.setColumnModel(sorter);
867         tableheader.setToolTipText(edu.umd.cs.findbugs.L10N.getLocalString("tooltip.reorder_message", "Drag to reorder tree folder and sort order"));
868         
869         tree = new JTree JavaDoc();
870         treeUI = (BasicTreeUI JavaDoc) tree.getUI();
871         tree.setLargeModel(true);
872         tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
873         tree.setCellRenderer(new BugRenderer());
874         tree.setRowHeight((int)(Driver.getFontSize() + 7));
875         if (false) {
876         
877         System.out.println("Left indent had been " + treeUI.getLeftChildIndent());
878         System.out.println("Right indent had been " + treeUI.getRightChildIndent());
879         treeUI.setLeftChildIndent(30 );
880         treeUI.setRightChildIndent(30 );
881         }
882         tree.setModel(new BugTreeModel(tree, sorter, new BugSet(new ArrayList JavaDoc<BugLeafNode>())));
883         setupTreeListeners();
884         curProject=BugLoader.getLoadedProject();
885         
886         
887         treeScrollPane = new JScrollPane JavaDoc(tree);
888         topPanel.setLayout(new BorderLayout JavaDoc());
889
890         topPanel.add(tableheader, BorderLayout.NORTH);
891         topPanel.add(treeScrollPane, BorderLayout.CENTER);
892         
893         return topPanel;
894     }
895     
896     public void newTree(final JTree JavaDoc newTree, final BugTreeModel newModel)
897     {
898         SwingUtilities.invokeLater(new Runnable JavaDoc()
899         {
900             public void run()
901             {
902                 tree = newTree;
903                 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
904                 tree.setLargeModel(true);
905                 tree.setCellRenderer(new BugRenderer());
906                 Container JavaDoc container = treeScrollPane.getParent();
907                 
908                 container.remove(treeScrollPane);
909                 treeScrollPane = new JScrollPane JavaDoc(newTree);
910                 container.add(treeScrollPane, BorderLayout.CENTER);
911                 setFontSizeHelper(container.getComponents(), Driver.getFontSize());
912                 tree.setRowHeight((int)(Driver.getFontSize() + 7));
913                 MainFrame.getInstance().getContentPane().validate();
914                 MainFrame.getInstance().getContentPane().repaint();
915                 
916                 setupTreeListeners();
917                 newModel.openPreviouslySelected(((BugTreeModel)(tree.getModel())).getOldSelectedBugs());
918                 MainFrame.this.getSorter().addColumnModelListener(newModel);
919                 FilterMatcher.addFilterListener(newModel);
920                 newTree.addTreeExpansionListener(newModel);
921                 MainFrame.this.setSorting(true);
922             }
923         });
924         
925     }
926     
927     boolean pleaseWait = false;
928     private boolean isPleaseWaitTree() {
929         return MainFrame.getInstance().getTree().getModel() instanceof BugTreeModel.PleaseWaitTreeModel;
930     }
931     private void setupTreeListeners()
932     {
933         tree.addTreeSelectionListener(new TreeSelectionListener JavaDoc(){
934             public void valueChanged(TreeSelectionEvent JavaDoc selectionEvent) {
935                     
936                 TreePath JavaDoc path = selectionEvent.getNewLeadSelectionPath();
937                 if (path != null)
938                 {
939                     saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
940
941                     Object JavaDoc lastPathComponent = path.getLastPathComponent();
942                     if (lastPathComponent instanceof BugLeafNode)
943                     {
944                         boolean beforeProjectChanged = projectChanged;
945                         currentSelectedBugLeaf = (BugLeafNode)lastPathComponent;
946                         currentSelectedBugAspects = null;
947                         syncBugInformation();
948                         setProjectChanged(beforeProjectChanged);
949                     }
950                     else
951                     {
952                         updateDesignationDisplay();
953                         currentSelectedBugLeaf = null;
954                         currentSelectedBugAspects = (BugAspects)lastPathComponent;
955                         syncBugInformation();
956                     }
957                 }
958                 if (isPleaseWaitTree() || pleaseWait) {
959                     return;
960                 }
961
962 // Debug.println("Tree selection count:" + tree.getSelectionCount());
963
if (tree.getSelectionCount() !=1)
964                 {
965                     Debug.println("Tree selection count not equal to 1, disabling comments tab" + selectionEvent);
966
967                     MainFrame.this.setUserCommentInputEnable(false);
968                     assert false : "Tree selection count is " + tree.getSelectionCount()+", disabling comments tab"
969                     + selectionEvent;
970                 }
971             }
972         });
973         
974         tree.addMouseListener(new MouseListener JavaDoc(){
975
976             public void mouseClicked(MouseEvent JavaDoc e) {
977                 TreePath JavaDoc path = tree.getPathForLocation(e.getX(), e.getY());
978                 
979                 if(path == null)
980                     return;
981                 
982                 if ((e.getButton() == MouseEvent.BUTTON3) ||
983                         (e.getButton() == MouseEvent.BUTTON1 && e.isControlDown())){
984                     
985                     if (tree.getModel().isLeaf(path.getLastPathComponent())){
986                         tree.setSelectionPath(path);
987                         bugPopupMenu.show(tree, e.getX(), e.getY());
988                     }
989                     else{
990                         tree.setSelectionPath(path);
991                         if (!(path.getParentPath()==null))//If the path's parent path is null, the root was selected, dont allow them to filter out the root.
992
branchPopupMenu.show(tree, e.getX(), e.getY());
993                     }
994                 }
995             }
996
997             public void mousePressed(MouseEvent JavaDoc arg0) {}
998             public void mouseReleased(MouseEvent JavaDoc arg0) {}
999             public void mouseEntered(MouseEvent JavaDoc arg0) {}
1000            public void mouseExited(MouseEvent JavaDoc arg0) {}
1001        });
1002    }
1003        
1004    
1005    void syncBugInformation (){
1006        if (currentSelectedBugLeaf != null) {
1007            BugInstance bug = currentSelectedBugLeaf.getBug();
1008            displayer.displaySource(bug, bug.getPrimarySourceLineAnnotation());
1009            comments.updateCommentsFromLeafInformation(currentSelectedBugLeaf);
1010            updateDesignationDisplay();
1011            comments.updateCommentsFromLeafInformation(currentSelectedBugLeaf);
1012            updateSummaryTab(currentSelectedBugLeaf);
1013        } else if (currentSelectedBugAspects != null) {
1014            updateDesignationDisplay();
1015            comments.updateCommentsFromNonLeafInformation(currentSelectedBugAspects);
1016            displayer.displaySource(null, null);
1017            clearSummaryTab();
1018        } else {
1019            displayer.displaySource(null, null);
1020            clearSummaryTab();
1021        }
1022    }
1023    
1024    /**
1025     * Clears the bottom tabs so not show bug information.
1026     *
1027     */

1028     void clearSourcePane(){
1029        SwingUtilities.invokeLater(new Runnable JavaDoc(){
1030            public void run(){
1031                setSourceTabTitle("Source");
1032                sourceCodeTextPane.setDocument(SourceCodeDisplay.SOURCE_NOT_RELEVANT);
1033            }
1034        });
1035    }
1036    
1037
1038    
1039    /**
1040     * @param b
1041     */

1042    private void setUserCommentInputEnable(boolean b) {
1043        comments.setUserCommentInputEnable(b);
1044        
1045    }
1046    /**
1047     * Creates the status bar of the GUI.
1048     * @return
1049     */

1050    JPanel JavaDoc statusBar()
1051    {
1052        JPanel JavaDoc statusBar = new JPanel JavaDoc();
1053        // statusBar.setBackground(Color.WHITE);
1054

1055        statusBar.setBorder(new BevelBorder JavaDoc(BevelBorder.LOWERED));
1056        statusBar.setLayout(new BorderLayout JavaDoc());
1057        statusBar.add(statusBarLabel,BorderLayout.WEST);
1058        
1059        JLabel JavaDoc logoLabel = new JLabel JavaDoc();
1060        
1061        ImageIcon JavaDoc logoIcon = new ImageIcon JavaDoc(MainFrame.class.getResource("logo_umd.png"));
1062        logoLabel.setIcon(logoIcon);
1063        statusBar.add(logoLabel, BorderLayout.EAST);
1064        
1065        return statusBar;
1066    }
1067    
1068    void updateStatusBar()
1069    {
1070        
1071        int countFilteredBugs = BugSet.countFilteredBugs();
1072        if (countFilteredBugs == 0)
1073            statusBarLabel.setText(" http://findbugs.sourceforge.net/");
1074        else if (countFilteredBugs == 1)
1075            statusBarLabel.setText(" 1 " + edu.umd.cs.findbugs.L10N.getLocalString("statusbar.bug_hidden", "bug hidden"));
1076        else
1077            statusBarLabel.setText(" " + countFilteredBugs + " " + edu.umd.cs.findbugs.L10N.getLocalString("statusbar.bugs_hidden", "bugs hidden"));
1078    }
1079    
1080    private void updateSummaryTab(BugLeafNode node)
1081    {
1082        final BugInstance bug = node.getBug();
1083
1084        final ArrayList JavaDoc<BugAnnotation> primaryAnnotations = new ArrayList JavaDoc<BugAnnotation>();
1085        boolean classIncluded = false;
1086        
1087        //This ensures the order of the primary annotations of the bug
1088
if(bug.getPrimarySourceLineAnnotation() != null)
1089            primaryAnnotations.add(bug.getPrimarySourceLineAnnotation());
1090        if(bug.getPrimaryMethod() != null)
1091            primaryAnnotations.add(bug.getPrimaryMethod());
1092        if(bug.getPrimaryField() != null)
1093            primaryAnnotations.add(bug.getPrimaryField());
1094        
1095        /*
1096         * This makes the primary class annotation appear only when
1097         * the visible field and method primary annotations don't have
1098         * the same class.
1099         */

1100        if(bug.getPrimaryClass() != null){
1101            FieldAnnotation primeField = bug.getPrimaryField();
1102            MethodAnnotation primeMethod = bug.getPrimaryMethod();
1103            ClassAnnotation primeClass = bug.getPrimaryClass();
1104            String JavaDoc fieldClass = "";
1105            String JavaDoc methodClass = "";
1106            if(primeField != null)
1107                fieldClass = primeField.getClassName();
1108            if(primeMethod != null)
1109                methodClass = primeMethod.getClassName();
1110            if((primaryAnnotations.size() < 2) || (!(primeClass.getClassName().equals(fieldClass) ||
1111                    primeClass.getClassName().equals(methodClass)))){
1112                primaryAnnotations.add(primeClass);
1113                classIncluded = true;
1114            }
1115        }
1116        
1117        final boolean classIncluded2 = classIncluded;
1118        
1119        SwingUtilities.invokeLater(new Runnable JavaDoc(){
1120            public void run(){
1121                summaryTopPanel.removeAll();
1122                
1123                summaryTopPanel.add(bugSummaryComponent(bug.getMessageWithoutPrefix(), bug));
1124                for(BugAnnotation b : primaryAnnotations)
1125                    summaryTopPanel.add(bugSummaryComponent(b, bug));
1126                
1127                
1128                if(!classIncluded2 && bug.getPrimaryClass() != null)
1129                    primaryAnnotations.add(bug.getPrimaryClass());
1130                
1131                for(Iterator JavaDoc<BugAnnotation> i = bug.annotationIterator(); i.hasNext();){
1132                    BugAnnotation b = i.next();
1133                    boolean cont = true;
1134                    for(BugAnnotation p : primaryAnnotations)
1135                        if(p == b)
1136                            cont = false;
1137                    
1138                    if(cont)
1139                        summaryTopPanel.add(bugSummaryComponent(b, bug));
1140                }
1141                
1142                summaryHtmlArea.setText(bug.getBugPattern().getDetailHTML());
1143                                
1144                summaryTopPanel.add(Box.createVerticalGlue());
1145                summaryTopPanel.revalidate();
1146                
1147                SwingUtilities.invokeLater(new Runnable JavaDoc(){
1148                    public void run(){
1149                        summaryHtmlScrollPane.getVerticalScrollBar().setValue(summaryHtmlScrollPane.getVerticalScrollBar().getMinimum());
1150                    }
1151                });
1152            }
1153        });
1154    }
1155    
1156    private void clearSummaryTab()
1157    {
1158        summaryHtmlArea.setText("");
1159        summaryTopPanel.removeAll();
1160        summaryTopPanel.revalidate();
1161    }
1162    
1163    /**
1164     * Creates initial summary tab and sets everything up.
1165     * @return
1166     */

1167    Component JavaDoc summaryTab()
1168    {
1169        int fontSize = (int) Driver.getFontSize();
1170        summaryTopPanel = new JPanel JavaDoc();
1171        summaryTopPanel.setLayout(new GridLayout JavaDoc(0,1));
1172        summaryTopPanel.setBorder(BorderFactory.createEmptyBorder(2,4,2,4));
1173        summaryTopPanel.setMinimumSize(new Dimension JavaDoc(fontSize * 50, fontSize*5));
1174        
1175        JPanel JavaDoc summaryTopOuter = new JPanel JavaDoc(new BorderLayout JavaDoc());
1176        summaryTopOuter.add(summaryTopPanel, BorderLayout.NORTH);
1177        
1178        summaryHtmlArea.setContentType("text/html");
1179        summaryHtmlArea.setEditable(false);
1180        summaryHtmlArea.setToolTipText(edu.umd.cs.findbugs.L10N.getLocalString("tooltip.longer_description", "This gives a longer description of the detected bug pattern"));
1181        summaryHtmlArea.addHyperlinkListener(new javax.swing.event.HyperlinkListener JavaDoc() {
1182                public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent JavaDoc evt) {
1183                    AboutDialog.editorPaneHyperlinkUpdate(evt);
1184                }
1185            });
1186        setStyleSheets();
1187        //JPanel temp = new JPanel(new BorderLayout());
1188
//temp.add(summaryTopPanel, BorderLayout.CENTER);
1189
JScrollPane JavaDoc summaryScrollPane = new JScrollPane JavaDoc(summaryTopOuter);
1190        summaryScrollPane.getVerticalScrollBar().setUnitIncrement( (int)Driver.getFontSize() );
1191
1192        JSplitPane JavaDoc splitP = new JSplitPane JavaDoc(JSplitPane.VERTICAL_SPLIT, false,
1193                summaryScrollPane, summaryHtmlScrollPane);
1194        splitP.setDividerLocation(85);
1195        splitP.setOneTouchExpandable(true);
1196        return splitP;
1197    }
1198    
1199    /**
1200     * Creates bug summary component. If obj is a string will create a JLabel
1201     * with that string as it's text and return it. If obj is an annotation
1202     * will return a JLabel with the annotation's toString(). If that
1203     * annotation is a SourceLineAnnotation or has a SourceLineAnnotation
1204     * connected to it and the source file is available will attach
1205     * a listener to the label.
1206     * @param obj
1207     * @param bug TODO
1208     * @return
1209     */

1210    private Component JavaDoc bugSummaryComponent(Object JavaDoc obj, BugInstance bug){
1211        JLabel JavaDoc label = new JLabel JavaDoc();
1212        label.setFont(label.getFont().deriveFont(Driver.getFontSize()));
1213        label.setFont(label.getFont().deriveFont(Font.PLAIN));
1214        label.setForeground(Color.BLACK);
1215        
1216        if(obj instanceof String JavaDoc){
1217            String JavaDoc str = (String JavaDoc) obj;
1218            label.setText(str);
1219        }
1220        else{
1221            
1222            BugAnnotation value = (BugAnnotation) obj;
1223            
1224            if(value == null)
1225                return new JLabel JavaDoc(edu.umd.cs.findbugs.L10N.getLocalString("summary.null", "null"));
1226            
1227            if(value instanceof SourceLineAnnotation){
1228                final SourceLineAnnotation note = (SourceLineAnnotation) value;
1229                if(sourceCodeExist(note)){
1230                    String JavaDoc srcStr = "";
1231                    int start = note.getStartLine();
1232                    int end = note.getEndLine();
1233                    if(start < 0 && end < 0)
1234                        srcStr = edu.umd.cs.findbugs.L10N.getLocalString("summary.source_code", "source code.");
1235                    else if(start == end)
1236                        srcStr = " [" + edu.umd.cs.findbugs.L10N.getLocalString("summary.line", "Line") + " " + start + "]";
1237                    else if(start < end)
1238                        srcStr = " [" + edu.umd.cs.findbugs.L10N.getLocalString("summary.lines", "Lines") + " " + start + " - " + end + "]";
1239                    
1240                    label.setToolTipText(edu.umd.cs.findbugs.L10N.getLocalString("tooltip.click_to_go_to", "Click to go to") + " " + srcStr);
1241                    
1242                    label.addMouseListener(new BugSummaryMouseListener(bug, label, note));
1243                }
1244                
1245                label.setText(note.toString());
1246            }
1247            else if(value instanceof PackageMemberAnnotation){
1248                PackageMemberAnnotation note = (PackageMemberAnnotation) value;
1249                final SourceLineAnnotation noteSrc = note.getSourceLines();
1250                String JavaDoc srcStr = "";
1251                if(sourceCodeExist(noteSrc) && noteSrc != null){
1252                    int start = noteSrc.getStartLine();
1253                    int end = noteSrc.getEndLine();
1254                    if(start < 0 && end < 0)
1255                        srcStr = edu.umd.cs.findbugs.L10N.getLocalString("summary.source_code", "source code.");
1256                    else if(start == end)
1257                        srcStr = " [" + edu.umd.cs.findbugs.L10N.getLocalString("summary.line", "Line") + " " + start + "]";
1258                    else if(start < end)
1259                        srcStr = " [" + edu.umd.cs.findbugs.L10N.getLocalString("summary.lines", "Lines") + " " + start + " - " + end + "]";
1260                    
1261                    if(!srcStr.equals("")){
1262                        label.setToolTipText(edu.umd.cs.findbugs.L10N.getLocalString("tooltip.click_to_go_to", "Click to go to") + " " + srcStr);
1263                        label.addMouseListener(new BugSummaryMouseListener(bug, label, noteSrc));
1264                    }
1265                }
1266                if(!srcStr.equals(edu.umd.cs.findbugs.L10N.getLocalString("summary.source_code", "source code.")))
1267                    label.setText(note.toString() + srcStr);
1268                else
1269                    label.setText(note.toString());
1270            }
1271            else{
1272                label.setText(((BugAnnotation) value).toString());
1273            }
1274        }
1275        
1276        return label;
1277    }
1278    
1279    /**
1280     * @author pugh
1281     */

1282    private final class InitializeGUI implements Runnable JavaDoc {
1283        public void run()
1284        {
1285            setTitle("FindBugs: " + Project.UNNAMED_PROJECT);
1286            
1287            guiLayout.initialize();
1288            bugPopupMenu = createBugPopupMenu();
1289            branchPopupMenu = createBranchPopUpMenu();
1290            comments.loadPrevCommentsList(GUISaveState.getInstance().getPreviousComments().toArray(new String JavaDoc[GUISaveState.getInstance().getPreviousComments().size()]));
1291            updateStatusBar();
1292            setBounds(GUISaveState.getInstance().getFrameBounds());
1293            Toolkit.getDefaultToolkit().setDynamicLayout(true);
1294            setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
1295            setJMenuBar(createMainMenuBar());
1296            setVisible(true);
1297            
1298            
1299            if (MAC_OS_X)
1300            {
1301                 try {
1302                    Class JavaDoc osxAdapter = Class.forName("edu.umd.cs.findbugs.gui2.OSXAdapter");
1303                    Method JavaDoc registerMethod = osxAdapter.getDeclaredMethod("registerMacOSXApplication", MainFrame.class);
1304                    if (registerMethod != null) {
1305                        registerMethod.invoke(osxAdapter, MainFrame.this);
1306                    }
1307                } catch (NoClassDefFoundError JavaDoc e) {
1308                    // This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
1309
// because OSXAdapter extends ApplicationAdapter in its def
1310
System.err.println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled (" + e + ")");
1311                } catch (ClassNotFoundException JavaDoc e) {
1312                    // This shouldn't be reached; if there's a problem with the OSXAdapter we should get the
1313
// above NoClassDefFoundError first.
1314
System.err.println("This version of Mac OS X does not support the Apple EAWT. Application Menu handling has been disabled (" + e + ")");
1315                } catch (Exception JavaDoc e) {
1316                    System.err.println("Exception while loading the OSXAdapter: " + e);
1317                    e.printStackTrace();
1318                    if (DEBUG) {
1319                        e.printStackTrace();
1320                    }
1321                }
1322            }
1323            String JavaDoc loadFromURL = SystemProperties.getProperty("findbugs.loadBugsFromURL");
1324            
1325            if (loadFromURL != null) {
1326                InputStream JavaDoc in;
1327                try {
1328                    in = new URL JavaDoc(loadFromURL).openConnection().getInputStream();
1329                    if (loadFromURL.endsWith(".gz"))
1330                        in = new GZIPInputStream JavaDoc(in);
1331                    BugTreeModel.pleaseWait(edu.umd.cs.findbugs.L10N.getLocalString("msg.loading_bugs_over_network_txt", "Loading bugs over network..."));
1332                    loadAnalysisFromInputStream(in);
1333                } catch (MalformedURLException JavaDoc e1) {
1334                    // TODO Auto-generated catch block
1335
e1.printStackTrace();
1336                    JOptionPane.showMessageDialog(MainFrame.this, "Error loading " +e1.getMessage());
1337                } catch (IOException JavaDoc e1) {
1338                    // TODO Auto-generated catch block
1339
e1.printStackTrace();
1340                    JOptionPane.showMessageDialog(MainFrame.this, "Error loading " +e1.getMessage());
1341                }
1342            }
1343        
1344            addComponentListener(new ComponentAdapter JavaDoc(){
1345                public void componentResized(ComponentEvent JavaDoc e){
1346                    comments.resized();
1347                }
1348            });
1349            
1350            addWindowListener(new WindowAdapter JavaDoc(){
1351                public void windowClosing(WindowEvent JavaDoc e) {
1352                    if(comments.hasFocus())
1353                        setProjectChanged(true);
1354                    callOnClose();
1355                }
1356            });
1357            Driver.removeSplashScreen();
1358        }
1359    }
1360
1361    /**
1362     * Listens for when cursor is over the label and when it is clicked.
1363     * When the cursor is over the label will make the label text blue
1364     * and the cursor the hand cursor. When clicked will take the
1365     * user to the source code tab and to the lines of code connected
1366     * to the SourceLineAnnotation.
1367     * @author Kristin Stephens
1368     *
1369     */

1370    private class BugSummaryMouseListener extends MouseAdapter JavaDoc{
1371        private BugInstance bugInstance;
1372        private JLabel JavaDoc label;
1373        private SourceLineAnnotation note;
1374        
1375        BugSummaryMouseListener(@NonNull BugInstance bugInstance, @NonNull JLabel JavaDoc label, @NonNull SourceLineAnnotation note){
1376            this.bugInstance = bugInstance;
1377            this.label = label;
1378            this.note = note;
1379        }
1380        
1381        public void mouseClicked(MouseEvent JavaDoc e) {
1382            displayer.displaySource(bugInstance, note);
1383        }
1384        public void mouseEntered(MouseEvent JavaDoc e){
1385            label.setForeground(Color.blue);
1386            setCursor(new Cursor JavaDoc(Cursor.HAND_CURSOR));
1387        }
1388        public void mouseExited(MouseEvent JavaDoc e){
1389            label.setForeground(Color.black);
1390            setCursor(new Cursor JavaDoc(Cursor.DEFAULT_CURSOR));
1391        }
1392    }
1393    
1394    /**
1395     * Checks if source code file exists/is available
1396     * @param note
1397     * @return
1398     */

1399    private boolean sourceCodeExist(SourceLineAnnotation note){
1400        try{
1401            sourceFinder.findSourceFile(note);
1402        }catch(FileNotFoundException JavaDoc e){
1403            return false;
1404        }catch(IOException JavaDoc e){
1405            return false;
1406        }
1407        return true;
1408    }
1409    
1410    private void setStyleSheets() {
1411        StyleSheet JavaDoc styleSheet = new StyleSheet JavaDoc();
1412        styleSheet.addRule("body {font-size: " + Driver.getFontSize() +"pt}");
1413        styleSheet.addRule("H1 {color: red; font-size: 120%; font-weight: bold;}");
1414        styleSheet.addRule("code {font-family: courier; font-size: " + Driver.getFontSize() +"pt}");
1415        htmlEditorKit.setStyleSheet(styleSheet);
1416        summaryHtmlArea.setEditorKit(htmlEditorKit);
1417    }
1418    
1419    JPanel JavaDoc createCommentsInputPanel() {
1420        return comments.createCommentsInputPanel();
1421    }
1422    
1423    /**
1424     * Creates the source code panel, but does not put anything in it.
1425     * @param text
1426     * @return
1427     */

1428    JPanel JavaDoc createSourceCodePanel()
1429    {
1430        Font JavaDoc sourceFont = new Font JavaDoc("Monospaced", Font.PLAIN, (int)Driver.getFontSize());
1431        sourceCodeTextPane.setFont(sourceFont);
1432        sourceCodeTextPane.setEditable(false);
1433        sourceCodeTextPane.getCaret().setSelectionVisible(true);
1434        sourceCodeTextPane.setDocument(SourceCodeDisplay.SOURCE_NOT_RELEVANT);
1435        sourceCodeScrollPane = new JScrollPane JavaDoc(sourceCodeTextPane);
1436        sourceCodeScrollPane.getVerticalScrollBar().setUnitIncrement(20);
1437
1438        JPanel JavaDoc panel = new JPanel JavaDoc();
1439        panel.setLayout(new BorderLayout JavaDoc());
1440        panel.add(sourceCodeScrollPane, BorderLayout.CENTER);
1441        
1442        panel.revalidate();
1443        if (DEBUG) System.out.println("Created source code panel");
1444        return panel;
1445    }
1446
1447    JPanel JavaDoc createSourceSearchPanel()
1448    {
1449        GridBagLayout JavaDoc gridbag = new GridBagLayout JavaDoc();
1450        GridBagConstraints JavaDoc c = new GridBagConstraints JavaDoc();
1451        JPanel JavaDoc thePanel = new JPanel JavaDoc();
1452        thePanel.setLayout(gridbag);
1453        c.gridx = 0;
1454        c.gridy = 0;
1455        c.weightx = 1.0;
1456        c.insets = new Insets JavaDoc(0, 5, 0, 5);
1457        c.fill = GridBagConstraints.HORIZONTAL;
1458        gridbag.setConstraints(sourceSearchTextField, c);
1459        thePanel.add(sourceSearchTextField);
1460        //add the buttons
1461
findButton.addActionListener(new ActionListener JavaDoc(){
1462            public void actionPerformed(ActionEvent JavaDoc evt){
1463                searchSource(0);
1464            }
1465        });
1466        c.gridx = 1;
1467        c.weightx = 0.0;
1468        c.fill = GridBagConstraints.NONE;
1469        gridbag.setConstraints(findButton, c);
1470        thePanel.add(findButton);
1471        findNextButton.addActionListener(new ActionListener JavaDoc(){
1472            public void actionPerformed(ActionEvent JavaDoc evt){
1473                searchSource(1);
1474            }
1475        });
1476        c.gridx = 2;
1477        c.weightx = 0.0;
1478        c.fill = GridBagConstraints.NONE;
1479        gridbag.setConstraints(findNextButton, c);
1480        thePanel.add(findNextButton);
1481        findPreviousButton.addActionListener(new ActionListener JavaDoc(){
1482            public void actionPerformed(ActionEvent JavaDoc evt){
1483                searchSource(2);
1484            }
1485        });
1486        c.gridx = 3;
1487        c.weightx = 0.0;
1488        c.fill = GridBagConstraints.NONE;
1489        gridbag.setConstraints(findPreviousButton, c);
1490        thePanel.add(findPreviousButton);
1491        return thePanel;
1492    }
1493
1494    void searchSource(int type)
1495    {
1496        int targetLineNum = -1;
1497        String JavaDoc targetString = sourceSearchTextField.getText();
1498        switch(type)
1499        {
1500        case 0: targetLineNum = displayer.find(targetString);
1501                break;
1502        case 1: targetLineNum = displayer.findNext(targetString);
1503                break;
1504        case 2: targetLineNum = displayer.findPrevious(targetString);
1505                break;
1506        }
1507        if(targetLineNum != -1)
1508            displayer.foundItem(targetLineNum);
1509    }
1510
1511    
1512
1513    /**
1514     * Sets the title of the source tabs for either docking or non-docking
1515     * versions.
1516     * @param title
1517     */

1518     void setSourceTabTitle(String JavaDoc title){
1519        guiLayout.setSourceTitle(title);
1520        
1521    }
1522    
1523        
1524    
1525        
1526    /**
1527     * Returns the SorterTableColumnModel of the MainFrame.
1528     * @return
1529     */

1530    SorterTableColumnModel getSorter()
1531    {
1532        return sorter;
1533    }
1534    
1535    /*
1536     * This is overridden for changing the font size
1537     */

1538    public void addNotify(){
1539        super.addNotify();
1540        
1541        float size = Driver.getFontSize();
1542        
1543        getJMenuBar().setFont(getJMenuBar().getFont().deriveFont(size));
1544        for(int i = 0; i < getJMenuBar().getMenuCount(); i++){
1545            for(int j = 0; j < getJMenuBar().getMenu(i).getMenuComponentCount(); j++){
1546                Component JavaDoc temp = getJMenuBar().getMenu(i).getMenuComponent(j);
1547                temp.setFont(temp.getFont().deriveFont(size));
1548            }
1549        }
1550        
1551        bugPopupMenu.setFont(bugPopupMenu.getFont().deriveFont(size));
1552        setFontSizeHelper(bugPopupMenu.getComponents(), size);
1553        
1554        branchPopupMenu.setFont(branchPopupMenu.getFont().deriveFont(size));
1555        setFontSizeHelper(branchPopupMenu.getComponents(), size);
1556        
1557    }
1558    
1559    public JTree JavaDoc getTree()
1560    {
1561        return tree;
1562    }
1563    
1564    static class CutAction extends TextAction JavaDoc {
1565        
1566        public CutAction() {
1567            super(edu.umd.cs.findbugs.L10N.getLocalString("txt.cut", "Cut"));
1568        }
1569
1570        public void actionPerformed( ActionEvent JavaDoc evt ) {
1571            JTextComponent JavaDoc text = getTextComponent( evt );
1572            
1573            if(text == null)
1574                return;
1575            
1576            text.cut();
1577        }
1578    }
1579    
1580    static class CopyAction extends TextAction JavaDoc {
1581        
1582        public CopyAction() {
1583            super(edu.umd.cs.findbugs.L10N.getLocalString("txt.copy", "Copy"));
1584        }
1585        
1586        public void actionPerformed( ActionEvent JavaDoc evt ) {
1587            JTextComponent JavaDoc text = getTextComponent( evt );
1588            
1589            if(text == null)
1590                return;
1591            
1592            text.copy();
1593        }
1594    }
1595    
1596    static class PasteAction extends TextAction JavaDoc {
1597        
1598        public PasteAction() {
1599            super(edu.umd.cs.findbugs.L10N.getLocalString("txt.paste", "Paste"));
1600        }
1601        
1602        public void actionPerformed( ActionEvent JavaDoc evt ) {
1603            JTextComponent JavaDoc text = getTextComponent( evt );
1604            
1605            if(text == null)
1606                return;
1607            
1608            text.paste();
1609        }
1610    }
1611
1612    public void setProject(Project p) {
1613        curProject=p;
1614        setTitle(p.getProjectFileName());
1615    }
1616
1617    public SourceFinder getSourceFinder()
1618    {
1619        return sourceFinder;
1620    }
1621    
1622    public void setSourceFinder(SourceFinder sf)
1623    {
1624        sourceFinder=sf;
1625    }
1626
1627    public void setRebuilding(boolean b)
1628    {
1629        tableheader.setReorderingAllowed(!b);
1630        preferencesMenuItem.setEnabled(!b);
1631        if (b)
1632            SorterDialog.getInstance().freeze();
1633        else
1634            SorterDialog.getInstance().thaw();
1635        recentProjectsMenu.setEnabled(!b);
1636    }
1637    
1638    public void setSorting(boolean b) {
1639        tableheader.setReorderingAllowed(b);
1640    }
1641    
1642    /**
1643     * Called when something in the project is changed and the change
1644     * needs to be saved.
1645     */

1646    /*
1647     * This should be called instead of using projectChanged = b.
1648     */

1649    public void setProjectChanged(boolean b){
1650        if(curProject == null)
1651            return;
1652        
1653        if(projectChanged == b)
1654            return;
1655        
1656        if(projectDirectory != null && projectDirectory.exists())
1657            saveProjectMenuItem.setEnabled(b);
1658        
1659        getRootPane().putClientProperty(WINDOW_MODIFIED, Boolean.valueOf(b));
1660
1661        projectChanged = b;
1662    }
1663    
1664    /*
1665     * DO NOT use the projectDirectory variable to figure out the current project directory in this function
1666     * use the passed in value, as that variable may or may not have been set to the passed in value at this point.
1667     */

1668    private boolean save(File JavaDoc dir)
1669    {
1670        if (curProject == null) {
1671            curProject = new Project();
1672            JOptionPane.showMessageDialog(MainFrame.this, "Null project; this is unexpected. "
1673                    +" Creating a new Project so the bugs can be saved, but please report this error.");
1674
1675        }
1676        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1677        
1678        dir.mkdir();
1679        updateDesignationDisplay();
1680        
1681        File JavaDoc f = new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".xml");
1682        File JavaDoc filtersAndSuppressions=new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".fas");
1683        //Saves current comment to current bug.
1684
saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1685
1686        BugSaver.saveBugs(f,BugSet.getMainBugSet(),curProject);
1687        try {
1688            filtersAndSuppressions.createNewFile();
1689            ProjectSettings.getInstance().save(new FileOutputStream JavaDoc(filtersAndSuppressions));
1690        } catch (IOException JavaDoc e) {
1691            Debug.println(e);
1692            return false;
1693        }
1694        setProjectChanged(false);
1695        MainFrame.this.setTitle("FindBugs: " + dir.getName());
1696        
1697        return true;
1698    }
1699    
1700    /**
1701     * @param currentSelectedBugLeaf2
1702     * @param currentSelectedBugAspects2
1703     */

1704    private void saveComments(BugLeafNode theNode, BugAspects theAspects) {
1705        comments.saveComments(theNode, theAspects);
1706        
1707    }
1708
1709    void saveComments() {
1710        comments.saveComments();
1711        
1712    }
1713    /**
1714     * Returns the color of the source code pane's background.
1715     * @return the color of the source code pane's background
1716     */

1717    public Color JavaDoc getSourceColor(){
1718        return sourceCodeTextPane.getBackground();
1719    }
1720
1721    /**
1722     * Show an error dialog.
1723     */

1724    public void error(String JavaDoc message) {
1725        JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
1726    }
1727    
1728    /**
1729     * Write a message to the console window.
1730     *
1731     * @param message the message to write
1732     */

1733    public void writeToLog(String JavaDoc message) {
1734        if (DEBUG)
1735            System.out.println(message);
1736        // consoleMessageArea.append(message);
1737
// consoleMessageArea.append("\n");
1738
}
1739    /**
1740     *
1741     */

1742    private void saveAnalysis() {
1743        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1744        
1745        if (curProject==null)
1746        {
1747            JOptionPane.showMessageDialog(MainFrame.this,edu.umd.cs.findbugs.L10N.getLocalString("dlg.no_proj_save_lbl", "There is no project to save"));
1748            return;
1749        }
1750        
1751        FBFileChooser chooser=new FBFileChooser();
1752        chooser.setFileFilter(new FindBugsAnalysisFileFilter());
1753        boolean saving=true;
1754        while (saving)
1755        {
1756
1757            int value=chooser.showSaveDialog(MainFrame.this);
1758            if (value==JFileChooser.APPROVE_OPTION)
1759            {
1760                saving=false;
1761                File JavaDoc xmlFile = chooser.getSelectedFile();
1762                
1763                if(!xmlFile.getName().endsWith(".xml"))
1764                    xmlFile = new File JavaDoc(xmlFile.getAbsolutePath()+".xml");
1765                
1766                if (xmlFile.exists())
1767                {
1768                    int response = JOptionPane.showConfirmDialog(chooser,
1769                            edu.umd.cs.findbugs.L10N.getLocalString("dlg.analysis_exists_lbl", "This analysis already exists.\nReplace it?"),
1770                            edu.umd.cs.findbugs.L10N.getLocalString("dlg.warning_ttl", "Warning!"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
1771                    
1772                    if(response == JOptionPane.OK_OPTION)
1773                        saving = false;
1774                    if(response == JOptionPane.CANCEL_OPTION){
1775                        saving = true;
1776                        continue;
1777                    }
1778                }
1779                BugSaver.saveBugs(xmlFile, BugSet.getMainBugSet(), MainFrame.this.curProject);
1780            }
1781        else return;
1782        }
1783    }
1784    /**
1785     *
1786     */

1787    private void loadAnalysis() {
1788        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1789
1790        FBFileChooser jfc = new FBFileChooser();
1791        jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
1792        jfc.setFileFilter(new FindBugsAnalysisFileFilter());
1793
1794        // jfc.setCurrentDirectory(GUISaveState.getInstance().getStarterDirectoryForLoadBugs());
1795
// this is done by FBFileChooser now.
1796

1797        while (true) {
1798            int returnValue = jfc.showOpenDialog(new JFrame JavaDoc());
1799
1800            if (returnValue != JFileChooser.APPROVE_OPTION)
1801                return;
1802
1803            File JavaDoc file = jfc.getSelectedFile();
1804
1805            if (!file.exists()) {
1806                JOptionPane.showMessageDialog(jfc, edu.umd.cs.findbugs.L10N.getLocalString("dlg.file_does_not_exist_lbl", "That file does not exist"));
1807                continue;
1808            }
1809            try {
1810                FileInputStream JavaDoc in = new FileInputStream JavaDoc(file);
1811                loadAnalysisFromInputStream(in);
1812                return;
1813            } catch (IOException JavaDoc e) {
1814                JOptionPane.showMessageDialog(jfc, e.getMessage());
1815            }
1816
1817
1818        }
1819    }
1820    /**
1821     * @param file
1822     * @return
1823     */

1824    private void loadAnalysisFromInputStream(final InputStream JavaDoc in) {
1825        setCursor(new Cursor JavaDoc(Cursor.WAIT_CURSOR));
1826        
1827        new Thread JavaDoc(new Runnable JavaDoc(){
1828            public void run()
1829            {
1830                BugTreeModel model=(BugTreeModel)tree.getModel();
1831// BugTreeModel.pleaseWait();
1832
MainFrame.this.setRebuilding(true);
1833                Project project = new Project();
1834                BugSet bs=BugLoader.loadBugs(project, in);
1835                MainFrame.this.setRebuilding(false);
1836                if (bs!=null)
1837                {
1838                    ProjectSettings.newInstance();
1839                    model.getOffListenerList();
1840                    updateDesignationDisplay();
1841                    model.changeSet(bs);
1842                    curProject=project;
1843                    MainFrame.this.updateStatusBar();
1844                    MainFrame.this.setTitle(project.getProjectFileName());
1845                    setCursor(new Cursor JavaDoc(Cursor.DEFAULT_CURSOR));
1846                    setProjectChanged(false);
1847                }
1848            }
1849        }).start();
1850        return;
1851    }
1852    /**
1853     *
1854     */

1855    private void redoAnalysis() {
1856        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1857        
1858        setCursor(new Cursor JavaDoc(Cursor.WAIT_CURSOR));
1859        new Thread JavaDoc()
1860        {
1861            public void run()
1862            {
1863                updateDesignationDisplay();
1864                BugSet bs=BugLoader.redoAnalysisKeepComments(curProject);
1865                
1866                if (bs!=null)
1867                {
1868                    displayer.clearCache();
1869                    //Dont clear data, the data's correct, just get the tree off the listener lists.
1870
((BugTreeModel) tree.getModel()).getOffListenerList();
1871                    ((BugTreeModel)tree.getModel()).changeSet(bs);
1872                    //curProject=BugLoader.getLoadedProject();
1873
}
1874                setCursor(new Cursor JavaDoc(Cursor.DEFAULT_CURSOR));
1875                setProjectChanged(true);
1876            }
1877        }.start();
1878    }
1879    /**
1880     *
1881     */

1882    private void mergeAnalysis() {
1883        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1884        
1885        setCursor(new Cursor JavaDoc(Cursor.WAIT_CURSOR));
1886        BugSet bs=BugLoader.combineBugHistories();
1887        if (bs!=null)
1888        {
1889            displayer.clearCache();
1890            ((BugTreeModel)tree.getModel()).getOffListenerList();
1891            updateDesignationDisplay();
1892            ((BugTreeModel)tree.getModel()).changeSet(bs);
1893            curProject=BugLoader.getLoadedProject();
1894        }
1895        setCursor(new Cursor JavaDoc(Cursor.DEFAULT_CURSOR));
1896        
1897        setProjectChanged(true);
1898    }
1899    /**
1900     *
1901     */

1902    private void openProject() {
1903        saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
1904        
1905        FBFileChooser jfc=new FBFileChooser();
1906        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1907        jfc.setFileFilter(FindBugsProjectFileFilter.INSTANCE);
1908        File JavaDoc xmlFile=null;
1909        if (projectChanged)
1910        {
1911            int response = JOptionPane.showConfirmDialog(MainFrame.this,
1912                    edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_current_changes", "The current project has been changed, Save current changes?")
1913                    ,edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_changes", "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
1914
1915            if (response == JOptionPane.YES_OPTION)
1916            {
1917                if (projectDirectory!=null)
1918                    save(projectDirectory);
1919                else
1920                    projectSaveAs();
1921            }
1922            else if (response == JOptionPane.CANCEL_OPTION)
1923                return;
1924            //IF no, do nothing.
1925
}
1926        
1927        boolean loading = true;
1928        while (loading)
1929        {
1930            int value=jfc.showOpenDialog(MainFrame.this);
1931            if(value==JFileChooser.APPROVE_OPTION){
1932                loading = false;
1933                final File JavaDoc dir = jfc.getSelectedFile();
1934                
1935                if(!dir.exists() || !dir.isDirectory())
1936                {
1937                    JOptionPane.showMessageDialog(null, edu.umd.cs.findbugs.L10N.getLocalString("dlg.proj_not_dir_warning_lbl", "Warning! This project is not a directory."));
1938                    loading = true;
1939                    continue;
1940                }
1941                else
1942                {
1943                    xmlFile= new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".xml");
1944                    File JavaDoc fasFile=new File JavaDoc(dir.getAbsolutePath() + File.separator + dir.getName() + ".fas");
1945
1946                    if (!xmlFile.exists())
1947                    {
1948                        JOptionPane.showMessageDialog(null, edu.umd.cs.findbugs.L10N.getLocalString("dlg.no_xml_data_lbl", "This directory does not contain saved bug XML data, please choose a different directory."));
1949                        loading=true;
1950                        continue;
1951                    }
1952                    
1953                    if (!fasFile.exists())
1954                    {
1955                        JOptionPane.showMessageDialog(MainFrame.this, edu.umd.cs.findbugs.L10N.getLocalString("dlg.filter_settings_not_found_lbl", "Filter settings not found, using default settings."));
1956                        try {
1957                            fasFile.createNewFile();
1958                            ProjectSettings.newInstance().save(new FileOutputStream JavaDoc(fasFile));
1959                        } catch (IOException JavaDoc e) {
1960                            if (MainFrame.DEBUG) System.err.println("Error saving new filter settings file, using default settings without saving these settings to the project.");
1961                            ProjectSettings.newInstance();
1962                        }
1963                    }
1964                    else
1965                    {
1966                        try
1967                        {
1968                            ProjectSettings.loadInstance(new FileInputStream JavaDoc(fasFile));
1969                        } catch (FileNotFoundException JavaDoc e)
1970                        {
1971                            //Impossible.
1972
if (MainFrame.DEBUG) System.err.println(".fas file not found, using default settings");
1973                            ProjectSettings.newInstance();
1974                        }
1975                    }
1976                    
1977                    final File JavaDoc extraFinalReferenceToXmlFile=xmlFile;
1978                    new Thread JavaDoc(new Runnable JavaDoc(){
1979                        public void run()
1980                        {
1981                            BugTreeModel model=(BugTreeModel)tree.getModel();
1982// Debug.println("please wait called by open menu item");
1983
BugTreeModel.pleaseWait();
1984                            MainFrame.this.setRebuilding(true);
1985                            Project project = new Project();
1986                            BugSet bs=BugLoader.loadBugs(project, extraFinalReferenceToXmlFile);
1987                            MainFrame.this.setRebuilding(false);
1988                            if (bs!=null)
1989                            {
1990                                editProjectMenuItem.setEnabled(true);
1991                                displayer.clearCache();
1992                                model.getOffListenerList();
1993                                updateDesignationDisplay();
1994                                model.changeSet(bs);
1995                                curProject=project;
1996                                projectDirectory=dir;
1997                                curProject.setProjectFileName(projectDirectory.getName());
1998                                MainFrame.this.setTitle("FindBugs: " + project.getProjectFileName());
1999                                MainFrame.getInstance().updateStatusBar();
2000                            }
2001                        }
2002                    }).start();
2003                }
2004            }
2005            else if (value==JFileChooser.CANCEL_OPTION)
2006            {
2007                return;
2008            }
2009            else
2010                loading = false;
2011        }
2012// List<String> projectPaths=new ArrayList<String>();
2013
ArrayList JavaDoc<File JavaDoc> xmlFiles=GUISaveState.getInstance().getRecentProjects();
2014
2015        if (!xmlFiles.contains(xmlFile))
2016        {
2017            GUISaveState.getInstance().addRecentProject(xmlFile);
2018            MainFrame.this.addRecentProjectToMenu(xmlFile);
2019        }
2020        
2021        //Clears the bottom tabs so they are blank. And makes comments
2022
//tab not enabled.
2023
clearSourcePane();
2024
2025        projectChanged = false;
2026    }
2027    /**
2028     *
2029     */

2030    private void newProjectMenu() {
2031        comments.saveComments(currentSelectedBugLeaf, currentSelectedBugAspects);
2032        new NewProjectWizard();
2033        
2034        newProject = true;
2035    }
2036    void updateDesignationDisplay() {
2037        comments.updateDesignationComboBox();
2038    }
2039    void addDesignationItem(JMenu JavaDoc menu, final String JavaDoc menuName, int keyEvent) {
2040        comments.addDesignationItem(menu, menuName, keyEvent);
2041    }
2042}
Popular Tags