1 19 20 package edu.umd.cs.findbugs.gui2; 21 22 import java.awt.BorderLayout ; 23 import java.awt.Button ; 24 import java.awt.Color ; 25 import java.awt.Component ; 26 import java.awt.Container ; 27 import java.awt.Cursor ; 28 import java.awt.Dimension ; 29 import java.awt.Event ; 30 import java.awt.Font ; 31 import java.awt.GridBagConstraints ; 32 import java.awt.GridBagLayout ; 33 import java.awt.GridLayout ; 34 import java.awt.Insets ; 35 import java.awt.Toolkit ; 36 import java.awt.event.ActionEvent ; 37 import java.awt.event.ActionListener ; 38 import java.awt.event.ComponentAdapter ; 39 import java.awt.event.ComponentEvent ; 40 import java.awt.event.KeyEvent ; 41 import java.awt.event.MouseAdapter ; 42 import java.awt.event.MouseEvent ; 43 import java.awt.event.MouseListener ; 44 import java.awt.event.WindowAdapter ; 45 import java.awt.event.WindowEvent ; 46 import java.io.File ; 47 import java.io.FileInputStream ; 48 import java.io.FileNotFoundException ; 49 import java.io.FileOutputStream ; 50 import java.io.IOException ; 51 import java.io.InputStream ; 52 import java.lang.reflect.Method ; 53 import java.net.MalformedURLException ; 54 import java.net.URL ; 55 import java.util.ArrayList ; 56 import java.util.Iterator ; 57 import java.util.zip.GZIPInputStream ; 58 59 import javax.swing.Action ; 60 import javax.swing.ActionMap ; 61 import javax.swing.BorderFactory ; 62 import javax.swing.Box ; 63 import javax.swing.ImageIcon ; 64 import javax.swing.JButton ; 65 import javax.swing.JButton ; 66 import javax.swing.JEditorPane ; 67 import javax.swing.JFileChooser ; 68 import javax.swing.JFrame ; 69 import javax.swing.JLabel ; 70 import javax.swing.JMenu ; 71 import javax.swing.JMenuBar ; 72 import javax.swing.JMenuItem ; 73 import javax.swing.JOptionPane ; 74 import javax.swing.JPanel ; 75 import javax.swing.JPopupMenu ; 76 import javax.swing.JScrollPane ; 77 import javax.swing.JSplitPane ; 78 import javax.swing.JTextArea ; 79 import javax.swing.JTextField ; 80 import javax.swing.JTextPane ; 81 import javax.swing.JTree ; 82 import javax.swing.KeyStroke ; 83 import javax.swing.SwingUtilities ; 84 import javax.swing.border.BevelBorder ; 85 import javax.swing.event.TreeSelectionEvent ; 86 import javax.swing.event.TreeSelectionListener ; 87 import javax.swing.plaf.basic.BasicTreeUI ; 88 import javax.swing.table.JTableHeader ; 89 import javax.swing.text.JTextComponent ; 90 import javax.swing.text.TextAction ; 91 import javax.swing.text.html.HTMLEditorKit ; 92 import javax.swing.text.html.StyleSheet ; 93 import javax.swing.tree.TreePath ; 94 import javax.swing.tree.TreeSelectionModel ; 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 ("serial") 115 116 122 125 public class MainFrame extends FBFrame implements LogSync 126 { 127 static JButton newButton(String key, String name) { 128 JButton b = new JButton (); 129 edu.umd.cs.findbugs.L10N.localiseButton(b, key, name, false); 130 return b; 131 } 132 static JMenuItem newJMenuItem(String key, String string, int vkF) { 133 JMenuItem m = new JMenuItem (); 134 edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, false); 135 m.setMnemonic(vkF); 136 return m; 137 138 } 139 static JMenuItem newJMenuItem(String key, String string) { 140 JMenuItem m = new JMenuItem (); 141 edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true); 142 return m; 143 144 } 145 static JMenu newJMenu(String key, String string) { 146 JMenu m = new JMenu (); 147 edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true); 148 return m; 149 } 150 JTree tree; 151 private BasicTreeUI treeUI; 152 boolean userInputEnabled; 153 154 static final String 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 sourceSearchTextField = new JTextField (SEARCH_TEXT_FIELD_SIZE); 161 private JButton findButton = newButton("button.find", "Find"); 162 private JButton findNextButton = newButton("button.findNext", "Find Next"); 163 private JButton 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 WINDOW_MODIFIED = "windowModified"; 169 170 NavigableTextPane sourceCodeTextPane = new NavigableTextPane(); 171 private JScrollPane sourceCodeScrollPane; 172 173 final CommentsArea comments; 174 private SorterTableColumnModel sorter; 175 private JTableHeader tableheader; 176 private JLabel statusBarLabel = new JLabel (); 177 178 private JPanel summaryTopPanel; 179 private final HTMLEditorKit htmlEditorKit = new HTMLEditorKit (); 180 private final JEditorPane summaryHtmlArea = new JEditorPane (); 181 private JScrollPane summaryHtmlScrollPane = new JScrollPane (summaryHtmlArea); 182 183 184 final private FindBugsLayoutManagerFactory findBugsLayoutManagerFactory; 185 final private FindBugsLayoutManager guiLayout; 186 187 191 boolean projectChanged = false; 192 final private JMenuItem editProjectMenuItem = newJMenuItem("menu.addRemoveFiles", "Add/Remove Files...", KeyEvent.VK_F); 193 final private JMenuItem saveProjectMenuItem = newJMenuItem("menu.save_item", "Save Project", KeyEvent.VK_S); 194 BugLeafNode currentSelectedBugLeaf; 195 BugAspects currentSelectedBugAspects; 196 private JPopupMenu bugPopupMenu; 197 private JPopupMenu branchPopupMenu; 198 private static MainFrame instance; 199 private JMenu recentProjectsMenu; 200 private JMenuItem preferencesMenuItem; 201 private File projectDirectory; 202 private Project curProject; 203 private JScrollPane treeScrollPane; 204 SourceFinder sourceFinder; 205 private Object lock = new Object (); 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 (); 213 instance=new MainFrame(factory); 214 instance.initializeGUI(); 215 } 216 221 222 static MainFrame getInstance() { 223 if (instance==null) throw new IllegalStateException (); 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 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 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 p: GUISaveState.getInstance().getRecentProjects()) 282 { 283 addRecentProjectToMenu(p); 284 } 285 } 286 287 private void addRecentProjectToMenu(final File 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 item=new JMenuItem (f.getName().substring(0,f.getName().length()-4)); 295 item.addActionListener(new ActionListener (){ 296 public void actionPerformed(ActionEvent e) 297 { 298 try 299 { 300 setCursor(new Cursor (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); 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); } 319 } 320 if (!exists) 321 throw new IllegalStateException ("User used a recent projects menu item that didn't exist."); 322 323 projectDirectory=f.getParentFile(); 324 File fasFile=new File (projectDirectory.getAbsolutePath() + File.separator + projectDirectory.getName() + ".fas"); 325 try 326 { 327 ProjectSettings.loadInstance(new FileInputStream (fasFile)); 328 } catch (FileNotFoundException exception) 329 { 330 ProjectSettings.newInstance(); 332 } 333 334 final File extraFinalReferenceToXmlFile=f; 335 new Thread (new Runnable (){ 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 } 356 BugTreeModel model=(BugTreeModel)tree.getModel(); 357 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 (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); } 398 } 399 if (!exists) 400 recentProjectsMenu.insert(item,0); 401 } 402 403 407 private JPopupMenu createBugPopupMenu() { 408 JPopupMenu popupMenu = new JPopupMenu (); 409 410 JMenuItem suppressMenuItem = newJMenuItem("menu.suppress", "Suppress this bug"); 411 412 suppressMenuItem.addActionListener(new ActionListener (){ 413 public void actionPerformed(ActionEvent evt){ 414 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 415 TreePath 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(); clearSourcePane(); 423 updateStatusBar(); 424 425 setProjectChanged(true); 426 } 427 428 }); 429 430 popupMenu.add(suppressMenuItem); 431 432 JMenuItem filterMenuItem = newJMenuItem("menu.filterBugsLikeThis", "Filter bugs like this"); 433 434 filterMenuItem.addActionListener(new ActionListener (){ 435 public void actionPerformed(ActionEvent evt){ 436 new NewFilterFromBug(currentSelectedBugLeaf.getBug()); 437 438 setProjectChanged(true); 439 } 440 }); 441 442 popupMenu.add(filterMenuItem); 443 444 JMenu 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 key : I18N.instance().getUserDesignationKeys(true)) { 449 String 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 463 private JPopupMenu createBranchPopUpMenu(){ 464 JPopupMenu popupMenu = new JPopupMenu (); 465 466 JMenuItem filterMenuItem = newJMenuItem("menu.filterTheseBugs", "Filter these bugs"); 467 468 filterMenuItem.addActionListener(new ActionListener () 469 { 470 public void actionPerformed(ActionEvent 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 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 key : I18N.instance().getUserDesignationKeys(true)) { 489 String name = I18N.instance().getUserDesignation(key); 490 addDesignationItem(changeDesignationMenu, name, keyEvents[i++]); 491 } 492 493 popupMenu.add(changeDesignationMenu); 494 495 return popupMenu; 496 } 497 498 502 protected JMenuBar createMainMenuBar() { 503 JMenuBar menuBar = new JMenuBar (); 504 505 JMenu fileMenu = newJMenu("menu.file_menu", "File"); 507 fileMenu.setMnemonic(KeyEvent.VK_F); 508 JMenu editMenu = newJMenu("menu.edit_menu", "Edit"); 509 editMenu.setMnemonic(KeyEvent.VK_E); 510 511 JMenuItem newProjectMenuItem = newJMenuItem("menu.new_item", "New Project", KeyEvent.VK_N); 513 JMenuItem 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 saveAsProjectMenuItem = newJMenuItem("menu.saveas_item", "Save Project As...", KeyEvent.VK_A); 518 JMenuItem importBugsMenuItem = newJMenuItem("menu.loadbugs_item", "Load Analysis...", KeyEvent.VK_L); 519 JMenuItem exportBugsMenuItem = newJMenuItem("menu.savebugs_item", "Save Analysis...", KeyEvent.VK_B); 520 JMenuItem redoAnalysis = newJMenuItem("menu.rerunAnalysis", "Redo Analysis", KeyEvent.VK_R); 521 JMenuItem mergeMenuItem = newJMenuItem("menu.mergeAnalysis", "Merge Analysis..."); 522 523 JMenuItem exitMenuItem = null; 524 if (!MAC_OS_X) { 525 exitMenuItem = newJMenuItem("menu.exit", "Exit", KeyEvent.VK_X); 526 exitMenuItem.addActionListener(new ActionListener (){ 527 public void actionPerformed(ActionEvent evt){ 528 callOnClose(); 529 } 530 }); 531 } 532 JMenu windowMenu = guiLayout.createWindowMenu(); 533 534 535 attachAccelaratorKey(newProjectMenuItem, KeyEvent.VK_N); 536 537 newProjectMenuItem.addActionListener(new ActionListener (){ 538 public void actionPerformed(ActionEvent evt){ 539 newProjectMenu(); 540 } 541 }); 542 543 attachAccelaratorKey(editProjectMenuItem, KeyEvent.VK_F); 544 editProjectMenuItem.addActionListener(new ActionListener () 545 { 546 public void actionPerformed(ActionEvent 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 (){ 556 public void actionPerformed(ActionEvent evt){ 557 openProject(); 558 } 559 }); 560 561 mergeMenuItem.setEnabled(true); 562 mergeMenuItem.addActionListener(new ActionListener (){ 563 public void actionPerformed(ActionEvent evt){ 564 mergeAnalysis(); 565 } 566 }); 567 568 redoAnalysis.setEnabled(true); 569 attachAccelaratorKey(redoAnalysis, KeyEvent.VK_R); 570 redoAnalysis.addActionListener(new ActionListener (){ 571 public void actionPerformed(ActionEvent evt){ 572 redoAnalysis(); 573 } 574 }); 575 576 saveProjectMenuItem.setEnabled(false); 577 attachAccelaratorKey(saveProjectMenuItem, KeyEvent.VK_S); 578 saveProjectMenuItem.addActionListener(new ActionListener (){ 579 public void actionPerformed(ActionEvent 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 (){ 589 public void actionPerformed(ActionEvent 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 (){ 599 public void actionPerformed(ActionEvent evt){ 600 loadAnalysis(); 601 } 602 }); 603 604 exportBugsMenuItem.setEnabled(true); 605 attachAccelaratorKey(exportBugsMenuItem, KeyEvent.VK_S, Event.ALT_MASK); 606 exportBugsMenuItem.addActionListener(new ActionListener (){ 607 public void actionPerformed(ActionEvent 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 JMenuItem cutMenuItem = new JMenuItem (new CutAction()); 637 JMenuItem copyMenuItem = new JMenuItem (new CopyAction()); 638 JMenuItem pasteMenuItem = new JMenuItem (new PasteAction()); 639 preferencesMenuItem = newJMenuItem("menu.filtersAndSupressions", "Filters/Suppressions..."); 640 JMenuItem sortMenuItem = newJMenuItem("menu.sortConfiguration", "Sort Configuration..."); 641 JMenuItem 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 (){ 648 public void actionPerformed(ActionEvent evt){ 649 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 650 PreferencesFrame.getInstance().setLocationRelativeTo(MainFrame.this); 651 PreferencesFrame.getInstance().setVisible(true); 652 } 653 }); 654 655 sortMenuItem.addActionListener(new ActionListener (){ 656 public void actionPerformed(ActionEvent 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 (){ 665 public void actionPerformed(ActionEvent 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 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(preferencesMenuItem); 683 editMenu.add(sortMenuItem); 684 685 menuBar.add(editMenu); 686 687 if (windowMenu != null) 688 menuBar.add(windowMenu); 689 690 final ActionMap map = tree.getActionMap(); 691 692 JMenu 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 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 key : I18N.instance().getUserDesignationKeys(true)) { 705 String name = I18N.instance().getUserDesignation(key); 706 addDesignationItem(designationMenu, name, keyEvents[i++]); 707 } 708 menuBar.add(designationMenu); 709 710 if (!MAC_OS_X) { 711 JMenu helpMenu = newJMenu("menu.help_menu", "Help"); 713 JMenuItem aboutItem = newJMenuItem("menu.about_item", "About FindBugs"); 714 helpMenu.add(aboutItem); 715 716 aboutItem.addActionListener(new java.awt.event.ActionListener () { 717 public void actionPerformed(java.awt.event.ActionEvent evt) { 718 about(); 719 } 720 }); 721 menuBar.add(helpMenu); 722 } 723 return menuBar; 724 } 725 729 private void addNavItem(final ActionMap map, JMenu navMenu, String menuNameKey, String menuNameDefault, String actionName, int keyEvent) { 730 JMenuItem toggleItem = newJMenuItem(menuNameKey, menuNameDefault); 731 toggleItem.addActionListener(treeActionAdapter(map, actionName)); 732 attachAccelaratorKey(toggleItem, keyEvent); 733 navMenu.add(toggleItem); 734 } 735 ActionListener treeActionAdapter(ActionMap map, String actionName) { 736 final Action selectPrevious = map.get(actionName); 737 return new ActionListener () { 738 public void actionPerformed(ActionEvent e) { 739 e.setSource(tree); 740 selectPrevious.actionPerformed(e); 741 }}; 742 } 743 static void attachAccelaratorKey(JMenuItem item, int keystroke) { 744 attachAccelaratorKey(item, keystroke, 0); 745 } 746 static void attachAccelaratorKey(JMenuItem item, int keystroke, 747 int additionalMask) { 748 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 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 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 xmlFile=new File (dir.getAbsolutePath() + File.separator + dir.getName() + ".xml"); 799 File fasFile=new File (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 xmlFile=new File (dir.getAbsolutePath() + File.separator + dir.getName() + ".xml"); 826 827 if (!exists) 829 { 830 GUISaveState.getInstance().addRecentProject(xmlFile); 831 } 832 833 MainFrame.this.addRecentProjectToMenu(xmlFile); 834 835 return true; 836 } 837 838 842 JPanel bugListPanel() 843 { 844 JPanel topPanel = new JPanel (); 845 topPanel.setMinimumSize(new Dimension (200,200)); 846 tableheader = new JTableHeader (); 847 tableheader.addMouseListener(new MouseAdapter (){ 850 851 public void mouseClicked(MouseEvent e) { 852 if (!tableheader.getReorderingAllowed()) 853 return; 854 if (e.getClickCount()==2) 855 SorterDialog.getInstance().setVisible(true); 856 } 857 858 public void mouseReleased(MouseEvent 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 (); 870 treeUI = (BasicTreeUI ) 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 <BugLeafNode>()))); 883 setupTreeListeners(); 884 curProject=BugLoader.getLoadedProject(); 885 886 887 treeScrollPane = new JScrollPane (tree); 888 topPanel.setLayout(new BorderLayout ()); 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 newTree, final BugTreeModel newModel) 897 { 898 SwingUtilities.invokeLater(new Runnable () 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 container = treeScrollPane.getParent(); 907 908 container.remove(treeScrollPane); 909 treeScrollPane = new JScrollPane (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 (){ 934 public void valueChanged(TreeSelectionEvent selectionEvent) { 935 936 TreePath path = selectionEvent.getNewLeadSelectionPath(); 937 if (path != null) 938 { 939 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 940 941 Object 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 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 (){ 975 976 public void mouseClicked(MouseEvent e) { 977 TreePath 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)) branchPopupMenu.show(tree, e.getX(), e.getY()); 993 } 994 } 995 } 996 997 public void mousePressed(MouseEvent arg0) {} 998 public void mouseReleased(MouseEvent arg0) {} 999 public void mouseEntered(MouseEvent arg0) {} 1000 public void mouseExited(MouseEvent 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 1028 void clearSourcePane(){ 1029 SwingUtilities.invokeLater(new Runnable (){ 1030 public void run(){ 1031 setSourceTabTitle("Source"); 1032 sourceCodeTextPane.setDocument(SourceCodeDisplay.SOURCE_NOT_RELEVANT); 1033 } 1034 }); 1035 } 1036 1037 1038 1039 1042 private void setUserCommentInputEnable(boolean b) { 1043 comments.setUserCommentInputEnable(b); 1044 1045 } 1046 1050 JPanel statusBar() 1051 { 1052 JPanel statusBar = new JPanel (); 1053 1055 statusBar.setBorder(new BevelBorder (BevelBorder.LOWERED)); 1056 statusBar.setLayout(new BorderLayout ()); 1057 statusBar.add(statusBarLabel,BorderLayout.WEST); 1058 1059 JLabel logoLabel = new JLabel (); 1060 1061 ImageIcon logoIcon = new ImageIcon (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 <BugAnnotation> primaryAnnotations = new ArrayList <BugAnnotation>(); 1085 boolean classIncluded = false; 1086 1087 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 1100 if(bug.getPrimaryClass() != null){ 1101 FieldAnnotation primeField = bug.getPrimaryField(); 1102 MethodAnnotation primeMethod = bug.getPrimaryMethod(); 1103 ClassAnnotation primeClass = bug.getPrimaryClass(); 1104 String fieldClass = ""; 1105 String 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 (){ 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 <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 (){ 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 1167 Component summaryTab() 1168 { 1169 int fontSize = (int) Driver.getFontSize(); 1170 summaryTopPanel = new JPanel (); 1171 summaryTopPanel.setLayout(new GridLayout (0,1)); 1172 summaryTopPanel.setBorder(BorderFactory.createEmptyBorder(2,4,2,4)); 1173 summaryTopPanel.setMinimumSize(new Dimension (fontSize * 50, fontSize*5)); 1174 1175 JPanel summaryTopOuter = new JPanel (new BorderLayout ()); 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 () { 1182 public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { 1183 AboutDialog.editorPaneHyperlinkUpdate(evt); 1184 } 1185 }); 1186 setStyleSheets(); 1187 JScrollPane summaryScrollPane = new JScrollPane (summaryTopOuter); 1190 summaryScrollPane.getVerticalScrollBar().setUnitIncrement( (int)Driver.getFontSize() ); 1191 1192 JSplitPane splitP = new JSplitPane (JSplitPane.VERTICAL_SPLIT, false, 1193 summaryScrollPane, summaryHtmlScrollPane); 1194 splitP.setDividerLocation(85); 1195 splitP.setOneTouchExpandable(true); 1196 return splitP; 1197 } 1198 1199 1210 private Component bugSummaryComponent(Object obj, BugInstance bug){ 1211 JLabel label = new JLabel (); 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 ){ 1217 String str = (String ) obj; 1218 label.setText(str); 1219 } 1220 else{ 1221 1222 BugAnnotation value = (BugAnnotation) obj; 1223 1224 if(value == null) 1225 return new JLabel (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 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 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 1282 private final class InitializeGUI implements Runnable { 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 [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 osxAdapter = Class.forName("edu.umd.cs.findbugs.gui2.OSXAdapter"); 1303 Method registerMethod = osxAdapter.getDeclaredMethod("registerMacOSXApplication", MainFrame.class); 1304 if (registerMethod != null) { 1305 registerMethod.invoke(osxAdapter, MainFrame.this); 1306 } 1307 } catch (NoClassDefFoundError e) { 1308 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 e) { 1312 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 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 loadFromURL = SystemProperties.getProperty("findbugs.loadBugsFromURL"); 1324 1325 if (loadFromURL != null) { 1326 InputStream in; 1327 try { 1328 in = new URL (loadFromURL).openConnection().getInputStream(); 1329 if (loadFromURL.endsWith(".gz")) 1330 in = new GZIPInputStream (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 e1) { 1334 e1.printStackTrace(); 1336 JOptionPane.showMessageDialog(MainFrame.this, "Error loading " +e1.getMessage()); 1337 } catch (IOException e1) { 1338 e1.printStackTrace(); 1340 JOptionPane.showMessageDialog(MainFrame.this, "Error loading " +e1.getMessage()); 1341 } 1342 } 1343 1344 addComponentListener(new ComponentAdapter (){ 1345 public void componentResized(ComponentEvent e){ 1346 comments.resized(); 1347 } 1348 }); 1349 1350 addWindowListener(new WindowAdapter (){ 1351 public void windowClosing(WindowEvent e) { 1352 if(comments.hasFocus()) 1353 setProjectChanged(true); 1354 callOnClose(); 1355 } 1356 }); 1357 Driver.removeSplashScreen(); 1358 } 1359 } 1360 1361 1370 private class BugSummaryMouseListener extends MouseAdapter { 1371 private BugInstance bugInstance; 1372 private JLabel label; 1373 private SourceLineAnnotation note; 1374 1375 BugSummaryMouseListener(@NonNull BugInstance bugInstance, @NonNull JLabel label, @NonNull SourceLineAnnotation note){ 1376 this.bugInstance = bugInstance; 1377 this.label = label; 1378 this.note = note; 1379 } 1380 1381 public void mouseClicked(MouseEvent e) { 1382 displayer.displaySource(bugInstance, note); 1383 } 1384 public void mouseEntered(MouseEvent e){ 1385 label.setForeground(Color.blue); 1386 setCursor(new Cursor (Cursor.HAND_CURSOR)); 1387 } 1388 public void mouseExited(MouseEvent e){ 1389 label.setForeground(Color.black); 1390 setCursor(new Cursor (Cursor.DEFAULT_CURSOR)); 1391 } 1392 } 1393 1394 1399 private boolean sourceCodeExist(SourceLineAnnotation note){ 1400 try{ 1401 sourceFinder.findSourceFile(note); 1402 }catch(FileNotFoundException e){ 1403 return false; 1404 }catch(IOException e){ 1405 return false; 1406 } 1407 return true; 1408 } 1409 1410 private void setStyleSheets() { 1411 StyleSheet styleSheet = new StyleSheet (); 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 createCommentsInputPanel() { 1420 return comments.createCommentsInputPanel(); 1421 } 1422 1423 1428 JPanel createSourceCodePanel() 1429 { 1430 Font sourceFont = new Font ("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 (sourceCodeTextPane); 1436 sourceCodeScrollPane.getVerticalScrollBar().setUnitIncrement(20); 1437 1438 JPanel panel = new JPanel (); 1439 panel.setLayout(new BorderLayout ()); 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 createSourceSearchPanel() 1448 { 1449 GridBagLayout gridbag = new GridBagLayout (); 1450 GridBagConstraints c = new GridBagConstraints (); 1451 JPanel thePanel = new JPanel (); 1452 thePanel.setLayout(gridbag); 1453 c.gridx = 0; 1454 c.gridy = 0; 1455 c.weightx = 1.0; 1456 c.insets = new Insets (0, 5, 0, 5); 1457 c.fill = GridBagConstraints.HORIZONTAL; 1458 gridbag.setConstraints(sourceSearchTextField, c); 1459 thePanel.add(sourceSearchTextField); 1460 findButton.addActionListener(new ActionListener (){ 1462 public void actionPerformed(ActionEvent 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 (){ 1472 public void actionPerformed(ActionEvent 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 (){ 1482 public void actionPerformed(ActionEvent 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 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 1518 void setSourceTabTitle(String title){ 1519 guiLayout.setSourceTitle(title); 1520 1521 } 1522 1523 1524 1525 1526 1530 SorterTableColumnModel getSorter() 1531 { 1532 return sorter; 1533 } 1534 1535 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 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 getTree() 1560 { 1561 return tree; 1562 } 1563 1564 static class CutAction extends TextAction { 1565 1566 public CutAction() { 1567 super(edu.umd.cs.findbugs.L10N.getLocalString("txt.cut", "Cut")); 1568 } 1569 1570 public void actionPerformed( ActionEvent evt ) { 1571 JTextComponent text = getTextComponent( evt ); 1572 1573 if(text == null) 1574 return; 1575 1576 text.cut(); 1577 } 1578 } 1579 1580 static class CopyAction extends TextAction { 1581 1582 public CopyAction() { 1583 super(edu.umd.cs.findbugs.L10N.getLocalString("txt.copy", "Copy")); 1584 } 1585 1586 public void actionPerformed( ActionEvent evt ) { 1587 JTextComponent text = getTextComponent( evt ); 1588 1589 if(text == null) 1590 return; 1591 1592 text.copy(); 1593 } 1594 } 1595 1596 static class PasteAction extends TextAction { 1597 1598 public PasteAction() { 1599 super(edu.umd.cs.findbugs.L10N.getLocalString("txt.paste", "Paste")); 1600 } 1601 1602 public void actionPerformed( ActionEvent evt ) { 1603 JTextComponent 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 1646 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 1668 private boolean save(File 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 f = new File (dir.getAbsolutePath() + File.separator + dir.getName() + ".xml"); 1682 File filtersAndSuppressions=new File (dir.getAbsolutePath() + File.separator + dir.getName() + ".fas"); 1683 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 1685 1686 BugSaver.saveBugs(f,BugSet.getMainBugSet(),curProject); 1687 try { 1688 filtersAndSuppressions.createNewFile(); 1689 ProjectSettings.getInstance().save(new FileOutputStream (filtersAndSuppressions)); 1690 } catch (IOException 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 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 1717 public Color getSourceColor(){ 1718 return sourceCodeTextPane.getBackground(); 1719 } 1720 1721 1724 public void error(String message) { 1725 JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); 1726 } 1727 1728 1733 public void writeToLog(String message) { 1734 if (DEBUG) 1735 System.out.println(message); 1736 } 1739 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 xmlFile = chooser.getSelectedFile(); 1762 1763 if(!xmlFile.getName().endsWith(".xml")) 1764 xmlFile = new File (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 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 1797 while (true) { 1798 int returnValue = jfc.showOpenDialog(new JFrame ()); 1799 1800 if (returnValue != JFileChooser.APPROVE_OPTION) 1801 return; 1802 1803 File 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 in = new FileInputStream (file); 1811 loadAnalysisFromInputStream(in); 1812 return; 1813 } catch (IOException e) { 1814 JOptionPane.showMessageDialog(jfc, e.getMessage()); 1815 } 1816 1817 1818 } 1819 } 1820 1824 private void loadAnalysisFromInputStream(final InputStream in) { 1825 setCursor(new Cursor (Cursor.WAIT_CURSOR)); 1826 1827 new Thread (new Runnable (){ 1828 public void run() 1829 { 1830 BugTreeModel model=(BugTreeModel)tree.getModel(); 1831 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 (Cursor.DEFAULT_CURSOR)); 1846 setProjectChanged(false); 1847 } 1848 } 1849 }).start(); 1850 return; 1851 } 1852 1855 private void redoAnalysis() { 1856 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 1857 1858 setCursor(new Cursor (Cursor.WAIT_CURSOR)); 1859 new Thread () 1860 { 1861 public void run() 1862 { 1863 updateDesignationDisplay(); 1864 BugSet bs=BugLoader.redoAnalysisKeepComments(curProject); 1865 1866 if (bs!=null) 1867 { 1868 displayer.clearCache(); 1869 ((BugTreeModel) tree.getModel()).getOffListenerList(); 1871 ((BugTreeModel)tree.getModel()).changeSet(bs); 1872 } 1874 setCursor(new Cursor (Cursor.DEFAULT_CURSOR)); 1875 setProjectChanged(true); 1876 } 1877 }.start(); 1878 } 1879 1882 private void mergeAnalysis() { 1883 saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); 1884 1885 setCursor(new Cursor (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 (Cursor.DEFAULT_CURSOR)); 1896 1897 setProjectChanged(true); 1898 } 1899 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 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 } 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 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 (dir.getAbsolutePath() + File.separator + dir.getName() + ".xml"); 1944 File fasFile=new File (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 (fasFile)); 1959 } catch (IOException 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 (fasFile)); 1969 } catch (FileNotFoundException e) 1970 { 1971 if (MainFrame.DEBUG) System.err.println(".fas file not found, using default settings"); 1973 ProjectSettings.newInstance(); 1974 } 1975 } 1976 1977 final File extraFinalReferenceToXmlFile=xmlFile; 1978 new Thread (new Runnable (){ 1979 public void run() 1980 { 1981 BugTreeModel model=(BugTreeModel)tree.getModel(); 1982 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 ArrayList <File > xmlFiles=GUISaveState.getInstance().getRecentProjects(); 2014 2015 if (!xmlFiles.contains(xmlFile)) 2016 { 2017 GUISaveState.getInstance().addRecentProject(xmlFile); 2018 MainFrame.this.addRecentProjectToMenu(xmlFile); 2019 } 2020 2021 clearSourcePane(); 2024 2025 projectChanged = false; 2026 } 2027 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 menu, final String menuName, int keyEvent) { 2040 comments.addDesignationItem(menu, menuName, keyEvent); 2041 } 2042} | Popular Tags |