📄 mainframe.java
字号:
/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA */package edu.umd.cs.findbugs.gui2;import java.awt.BorderLayout;import java.awt.CardLayout;import java.awt.Color;import java.awt.Component;import java.awt.Container;import java.awt.Cursor;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Font;import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.GridLayout;import java.awt.Insets;import java.awt.Toolkit;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ComponentAdapter;import java.awt.event.ComponentEvent;import java.awt.event.KeyEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Method;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.zip.GZIPInputStream;import javax.swing.Action;import javax.swing.ActionMap;import javax.swing.BorderFactory;import javax.swing.Box;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JEditorPane;import javax.swing.JFileChooser;import javax.swing.JLabel;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JPopupMenu;import javax.swing.JScrollPane;import javax.swing.JSplitPane;import javax.swing.JTable;import javax.swing.JTextField;import javax.swing.JToolTip;import javax.swing.JTree;import javax.swing.KeyStroke;import javax.swing.SwingUtilities;import javax.swing.UIManager;import javax.swing.border.BevelBorder;import javax.swing.event.TreeModelEvent;import javax.swing.event.TreeModelListener;import javax.swing.event.TreeSelectionEvent;import javax.swing.event.TreeSelectionListener;import javax.swing.filechooser.FileFilter;import javax.swing.plaf.FontUIResource;import javax.swing.plaf.basic.BasicTreeUI;import javax.swing.table.DefaultTableModel;import javax.swing.table.JTableHeader;import javax.swing.text.JTextComponent;import javax.swing.text.TextAction;import javax.swing.text.html.HTMLEditorKit;import javax.swing.text.html.StyleSheet;import javax.swing.tree.TreePath;import javax.swing.tree.TreeSelectionModel;import edu.umd.cs.findbugs.BugAnnotation;import edu.umd.cs.findbugs.BugCollection;import edu.umd.cs.findbugs.BugInstance;import edu.umd.cs.findbugs.ClassAnnotation;import edu.umd.cs.findbugs.FieldAnnotation;import edu.umd.cs.findbugs.FindBugsDisplayFeatures;import edu.umd.cs.findbugs.I18N;import edu.umd.cs.findbugs.MethodAnnotation;import edu.umd.cs.findbugs.PackageMemberAnnotation;import edu.umd.cs.findbugs.Project;import edu.umd.cs.findbugs.SortedBugCollection;import edu.umd.cs.findbugs.SourceLineAnnotation;import edu.umd.cs.findbugs.SuppressionMatcher;import edu.umd.cs.findbugs.SystemProperties;import edu.umd.cs.findbugs.annotations.CheckForNull;import edu.umd.cs.findbugs.annotations.NonNull;import edu.umd.cs.findbugs.ba.AnalysisContext;import edu.umd.cs.findbugs.ba.SourceFinder;import edu.umd.cs.findbugs.filter.Filter;import edu.umd.cs.findbugs.filter.LastVersionMatcher;import edu.umd.cs.findbugs.filter.Matcher;import edu.umd.cs.findbugs.gui.ConsoleLogger;import edu.umd.cs.findbugs.gui.LogSync;import edu.umd.cs.findbugs.gui.Logger;import edu.umd.cs.findbugs.gui2.BugTreeModel.BranchOperationException;import edu.umd.cs.findbugs.gui2.BugTreeModel.TreeModification;import edu.umd.cs.findbugs.sourceViewer.NavigableTextPane;@SuppressWarnings("serial")/* * This is where it all happens... seriously... all of it... * All the menus are set up, all the listeners, all the frames, dockable window functionality * There is no one style used, no one naming convention, its all just kinda here. This is another one of those * classes where no one knows quite why it works. *//** * The MainFrame is just that, the main application window where just about everything happens. */public class MainFrame extends FBFrame implements LogSync{ static JButton newButton(String key, String name) { JButton b = new JButton(); edu.umd.cs.findbugs.L10N.localiseButton(b, key, name, false); return b; } static JMenuItem newJMenuItem(String key, String string, int vkF) { JMenuItem m = new JMenuItem(); edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, false); m.setMnemonic(vkF); return m; } static JMenuItem newJMenuItem(String key, String string) { JMenuItem m = new JMenuItem(); edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true); return m; } static JMenu newJMenu(String key, String string) { JMenu m = new JMenu(); edu.umd.cs.findbugs.L10N.localiseButton(m, key, string, true); return m; } JTree tree; private BasicTreeUI treeUI; boolean userInputEnabled; static boolean isMacLookAndFeel() { return UIManager.getLookAndFeel().getClass().getName().startsWith("apple"); } static final String DEFAULT_SOURCE_CODE_MSG = edu.umd.cs.findbugs.L10N.getLocalString("msg.nosource_txt", "No available source"); static final int COMMENTS_TAB_STRUT_SIZE = 5; static final int COMMENTS_MARGIN = 5; static final int SEARCH_TEXT_FIELD_SIZE = 32; static final String TITLE_START_TXT = "FindBugs: "; private JTextField sourceSearchTextField = new JTextField(SEARCH_TEXT_FIELD_SIZE); private JButton findButton = newButton("button.find", "Find"); private JButton findNextButton = newButton("button.findNext", "Find Next"); private JButton findPreviousButton = newButton("button.findPrev", "Find Previous"); public static final boolean DEBUG = SystemProperties.getBoolean("gui2.debug"); static final boolean MAC_OS_X = SystemProperties.getProperty("os.name").toLowerCase().startsWith("mac os x"); final static String WINDOW_MODIFIED = "windowModified"; NavigableTextPane sourceCodeTextPane = new NavigableTextPane(); private JScrollPane sourceCodeScrollPane; final CommentsArea comments; private SorterTableColumnModel sorter; private JTableHeader tableheader; private JLabel statusBarLabel = new JLabel(); private JPanel summaryTopPanel; private final HTMLEditorKit htmlEditorKit = new HTMLEditorKit(); private final JEditorPane summaryHtmlArea = new JEditorPane(); private JScrollPane summaryHtmlScrollPane = new JScrollPane(summaryHtmlArea); final private FindBugsLayoutManagerFactory findBugsLayoutManagerFactory; final private FindBugsLayoutManager guiLayout; /* To change this value must use setProjectChanged(boolean b). * This is because saveProjectItemMenu is dependent on it for when * saveProjectMenuItem should be enabled. */ boolean projectChanged = false; final private JMenuItem reconfigMenuItem = newJMenuItem("menu.reconfig", "Reconfigure...", KeyEvent.VK_F); private JMenuItem redoAnalysis; BugLeafNode currentSelectedBugLeaf; BugAspects currentSelectedBugAspects; private JPopupMenu bugPopupMenu; private JPopupMenu branchPopupMenu; private static MainFrame instance; private RecentMenu recentMenuCache; private JMenu recentMenu; private JMenuItem preferencesMenuItem; private Project curProject = new Project(); private JScrollPane treeScrollPane; SourceFinder sourceFinder; private Object lock = new Object(); private boolean newProject = false; private Class osxAdapter; private Method osxPrefsEnableMethod; private Logger logger = new ConsoleLogger(this); SourceCodeDisplay displayer = new SourceCodeDisplay(this); private SaveType saveType = SaveType.NOT_KNOWN; FBFileChooser saveOpenFileChooser; @CheckForNull private File saveFile = null; enum SaveReturn {SAVE_SUCCESSFUL, SAVE_IO_EXCEPTION, SAVE_ERROR}; JMenuItem saveMenuItem = newJMenuItem("menu.save_item", "Save", KeyEvent.VK_S); static void makeInstance(FindBugsLayoutManagerFactory factory) { if (instance != null) throw new IllegalStateException(); instance=new MainFrame(factory); instance.initializeGUI(); } /** * @param string * @param vkF * @return */ static MainFrame getInstance() { if (instance==null) throw new IllegalStateException(); return instance; } private void initializeGUI() { SwingUtilities.invokeLater(new InitializeGUI()); } private MainFrame(FindBugsLayoutManagerFactory factory) { this.findBugsLayoutManagerFactory = factory; this.guiLayout = factory.getInstance(this); this.comments = new CommentsArea(this); FindBugsDisplayFeatures.setAbridgedMessages(true); } /** * Show About */ void about() { AboutDialog dialog = new AboutDialog(this, logger, true); dialog.setSize(600, 554); dialog.setLocationRelativeTo(this); dialog.setVisible(true); } /** * Show Preferences */ void preferences() { saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); PreferencesFrame.getInstance().setLocationRelativeTo(MainFrame.this); PreferencesFrame.getInstance().setVisible(true); } /** * enable/disable preferences menu */ void enablePreferences(boolean b) { preferencesMenuItem.setEnabled(b); if (MAC_OS_X) { if (osxPrefsEnableMethod != null) { Object args[] = {Boolean.valueOf(b)}; try { osxPrefsEnableMethod.invoke(osxAdapter, args); } catch (Exception e) { System.err.println("Exception while enabling Preferences menu: " + e); } } } } /** * This method is called when the application is closing. This is either by * the exit menuItem or by clicking on the window's system menu. */ void callOnClose(){ comments.saveComments(currentSelectedBugLeaf, currentSelectedBugAspects); if(projectChanged){ int value = JOptionPane.showConfirmDialog(MainFrame.this, edu.umd.cs.findbugs.L10N.getLocalString("msg.you_are_closing_txt", "You are closing") + " " + edu.umd.cs.findbugs.L10N.getLocalString("msg.without_saving_txt", "without saving. Do you want to save?"), edu.umd.cs.findbugs.L10N.getLocalString("msg.confirm_save_txt", "Do you want to save?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if(value == JOptionPane.CANCEL_OPTION || value == JOptionPane.CLOSED_OPTION) return ; else if(value == JOptionPane.YES_OPTION){ if(saveFile == null){ if(!saveAs()) return; } else save(); } } GUISaveState.getInstance().setPreviousComments(comments.prevCommentsList); guiLayout.saveState(); GUISaveState.getInstance().setFrameBounds( getBounds() ); GUISaveState.getInstance().save(); System.exit(0); } /* * A lot of if(false) here is for switching from special cases based on localSaveType * to depending on the SaveType.forFile(f) method. Can delete when sure works. */ JMenuItem createRecentItem(final File f, final SaveType localSaveType) { if (DEBUG) System.out.println("createRecentItem("+f+", "+localSaveType +")"); String name = f.getName(); final JMenuItem item=new JMenuItem(name); item.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { try { setCursor(new Cursor(Cursor.WAIT_CURSOR)); if (!f.exists()) { JOptionPane.showMessageDialog(null,edu.umd.cs.findbugs.L10N.getLocalString("msg.proj_not_found", "This project can no longer be found")); GUISaveState.getInstance().fileNotFound(f); return; } GUISaveState.getInstance().fileReused(f);//Move to front in GUISaveState, so it will be last thing to be removed from the list MainFrame.this.recentMenuCache.addRecentFile(f); if (!f.exists()) throw new IllegalStateException ("User used a recent projects menu item that didn't exist."); //Moved this outside of the thread, and above the line saveFile=f.getParentFile() //Since if this save goes on in the thread below, there is no way to stop the save from //overwriting the files we are about to load. if (curProject != null && projectChanged) { int response = JOptionPane.showConfirmDialog(MainFrame.this, edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_current_changes", "The current project has been changed, Save current changes?") ,edu.umd.cs.findbugs.L10N.getLocalString("dlg.save_changes", "Save Changes?"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); if (response == JOptionPane.YES_OPTION) { if(saveFile != null) save(); else saveAs(); } else if (response == JOptionPane.CANCEL_OPTION) return; //IF no, do nothing. } SaveType st = SaveType.forFile(f); boolean result = true; switch(st){ case PROJECT: openProject(f); break; case XML_ANALYSIS: result = openAnalysis(f, st); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -