/* * 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.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Iterator; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.table.DefaultTableModel; import javax.swing.tree.TreeModel; import edu.umd.cs.findbugs.filter.Filter; import edu.umd.cs.findbugs.filter.Matcher; /** * User Preferences */ /* * * Preferences, which should really be renamed Filters And Suppressions (fas, like fas file!) * since thats all that's actually here now * */ @SuppressWarnings("serial") public class PreferencesFrame extends FBDialog { private static int PROPERTIES_TAB = 0; private static int FILTERS_TAB = 1; private static int SUPPRESSIONS_TAB = 2; JTabbedPane mainTabPane; private static PreferencesFrame instance; private CheckBoxList filterCheckBoxList = new CheckBoxList(); private JButton addButton; JButton removeButton; JButton removeAllButton; boolean frozen=false; //Variables for Properties tab. private JTextField tabTextField; private JTextField fontTextField; private JTextField packagePrefixLengthTextField; private static int TAB_MIN = 1; private static int TAB_MAX = 20; private static int FONT_MIN = 10; private static int FONT_MAX = 99; public static PreferencesFrame getInstance() { // MainFrame.getInstance().getSorter().freezeOrder(); if(instance == null) instance = new PreferencesFrame(); return instance; } private PreferencesFrame(){ setTitle(edu.umd.cs.findbugs.L10N.getLocalString("dlg.fil_sup_ttl", "Filters/Suppressions")); setModal(true); mainTabPane = new JTabbedPane(); mainTabPane.add("Properties", createPropertiesPane()); mainTabPane.add(edu.umd.cs.findbugs.L10N.getLocalString("pref.filters", "Filters"), createFilterPane()); MainFrame.getInstance().updateStatusBar(); getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); JPanel top = new JPanel(); top.setLayout(new BoxLayout(top, BoxLayout.X_AXIS)); top.add(Box.createHorizontalStrut(5)); top.add(mainTabPane); top.add(Box.createHorizontalStrut(5)); JPanel bottom = new JPanel(); bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS)); bottom.add(Box.createHorizontalGlue()); bottom.add(new JButton(new AbstractAction(edu.umd.cs.findbugs.L10N.getLocalString("pref.close", "Close")) { public void actionPerformed(ActionEvent evt) { // MainFrame.getInstance().getSorter().thawOrder(); PreferencesFrame.this.setVisible(false); TreeModel bt= (MainFrame.getInstance().getTree().getModel()); if (bt instanceof BugTreeModel) ((BugTreeModel)bt).checkSorter(); resetPropertiesPane(); } })); bottom.add(Box.createHorizontalStrut(5)); add(Box.createVerticalStrut(5)); add(top); add(Box.createVerticalStrut(5)); add(bottom); add(Box.createVerticalStrut(5)); setDefaultCloseOperation(HIDE_ON_CLOSE); pack(); } // /** // * Creates the general tab. This lets the user change the font // * size and the total number of possible previous comments. // * @return // */ // private JPanel createGeneralPane() { // JPanel generalPanel = new JPanel(); // // generalPanel.add(new JLabel("Clear Recent Projects List")); // JButton clearButton=new JButton("Clear"); // clearButton.addActionListener(new ActionListener() // { // public void actionPerformed(ActionEvent e) // { // GUISaveState.getInstance().clear(); // } // }); // return generalPanel; // } // private JPanel createPropertiesPane() { JPanel contentPanel = new JPanel(new BorderLayout()); JPanel mainPanel = new JPanel(); float currFS = Driver.getFontSize(); JPanel temp = new JPanel(); temp.add(new JLabel("Tab size")); tabTextField = new JTextField(Integer.toString(GUISaveState.getInstance().getTabSize())); tabTextField.setPreferredSize(new Dimension((int)(currFS*2), (int)(currFS*1.3))); temp.add(tabTextField); mainPanel.add(temp); mainPanel.add(Box.createVerticalStrut(5)); temp = new JPanel(); temp.add(new JLabel("Font size")); fontTextField = new JTextField(Float.toString(GUISaveState.getInstance().getFontSize())); fontTextField.setPreferredSize(new Dimension((int)(currFS*3), (int)(currFS*1.3))); temp.add(fontTextField); mainPanel.add(temp); mainPanel.add(Box.createVerticalGlue()); temp = new JPanel(); temp.add(new JLabel("Package prefix length")); packagePrefixLengthTextField = new JTextField(Integer.toString(GUISaveState.getInstance().getPackagePrefixSegments())); packagePrefixLengthTextField.setPreferredSize(new Dimension((int)(currFS*2), (int)(currFS*1.3))); temp.add(packagePrefixLengthTextField); mainPanel.add(temp); mainPanel.add(Box.createVerticalGlue()); contentPanel.add(mainPanel, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(); bottomPanel.add(new JButton(new AbstractAction("Apply") { public void actionPerformed(ActionEvent evt) { changeTabSize(); changeFontSize(); changePackagePrefixLength(); } })); bottomPanel.add(new JButton(new AbstractAction("Reset") { public void actionPerformed(ActionEvent evt) { resetPropertiesPane(); } })); contentPanel.add(bottomPanel, BorderLayout.SOUTH); addWindowListener(new WindowAdapter(){ @Override public void windowDeactivated(WindowEvent e) { resetPropertiesPane(); } }); return contentPanel; } private void changeTabSize(){ int tabSize = 0; try{ tabSize = Integer.decode(tabTextField.getText()).intValue(); } catch(NumberFormatException exc){ JOptionPane.showMessageDialog(instance, "Error in tab size field.", "Tab Size Error", JOptionPane.INFORMATION_MESSAGE); return; } if(tabSize < TAB_MIN || tabSize > TAB_MAX){ JOptionPane.showMessageDialog(instance, "Tab size exceedes range ("+TAB_MIN+" - "+TAB_MAX+").", "Tab Size Excedes Range", JOptionPane.INFORMATION_MESSAGE); return; } if(tabSize != GUISaveState.getInstance().getTabSize()){ GUISaveState.getInstance().setTabSize(tabSize); MainFrame.getInstance().displayer.clearCache(); //This causes the GUI to redisplay the current code MainFrame.getInstance().syncBugInformation(); } } private void changeFontSize(){ float fontSize = 0; try{ fontSize = Float.parseFloat(fontTextField.getText()); } catch(NumberFormatException exc){ JOptionPane.showMessageDialog(instance, "Error in font size field.", "Font Size Error", JOptionPane.INFORMATION_MESSAGE); return; } if(fontSize < FONT_MIN || fontSize > FONT_MAX){ JOptionPane.showMessageDialog(instance, "Font size exceedes range ("+FONT_MIN+" - "+FONT_MAX+").", "Font Size Exceedes Range", JOptionPane.INFORMATION_MESSAGE); return; } if(fontSize != GUISaveState.getInstance().getFontSize()){ GUISaveState.getInstance().setFontSize(fontSize); JOptionPane.showMessageDialog(instance, "To implement the new font size please restart FindBugs.", "Changing Font", JOptionPane.INFORMATION_MESSAGE); } } private void changePackagePrefixLength(){ int value = 0; try{ value = Integer.parseInt(packagePrefixLengthTextField.getText()); } catch(NumberFormatException exc){ JOptionPane.showMessageDialog(instance, "Error in package prefix length field.", "Package Prefix Length Error", JOptionPane.INFORMATION_MESSAGE); return; } if(value < 1 || value > 12){ JOptionPane.showMessageDialog(instance, "package prefix length exceedes range ("+1+" - "+12+").", "package prefix lengthe exceedes range", JOptionPane.INFORMATION_MESSAGE); return; } if (value !=GUISaveState.getInstance().getPackagePrefixSegments()) { GUISaveState.getInstance().setPackagePrefixSegments(value); BugTreeModel bt=(BugTreeModel) (MainFrame.getInstance().getTree().getModel()); bt.needToRebuild(); bt.checkSorter(); } } private void resetPropertiesPane() { tabTextField.setText(Integer.toString(GUISaveState.getInstance().getTabSize())); fontTextField.setText(Float.toString(GUISaveState.getInstance().getFontSize())); } /** * Create a JPanel to display the filtering controls. */ private JPanel createFilterPane() { addButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.add_dot_btn", "Add...")); removeButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.remove_btn", "Remove")); removeAllButton = new JButton(edu.umd.cs.findbugs.L10N.getLocalString("dlg.remove_all_btn", "Remove All")); JPanel filterPanel = new JPanel(); filterPanel.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridheight = 4; gbc.gridwidth = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; gbc.weighty = 1; filterPanel.add(new JScrollPane(filterCheckBoxList), gbc); updateFilterPanel(); gbc.gridheight = 1; gbc.gridx = 1; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 0; gbc.weighty = 0; filterPanel.add(addButton, gbc); addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { NewFilterFrame.open(); } }); gbc.gridy = 1; gbc.insets = new Insets(5, 0, 0, 0); filterPanel.add(removeButton, gbc); removeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { Object[] selected=filterCheckBoxList.getSelectedValues(); boolean needsRebuild=false; if (selected.length == 0) return; for (Object o: selected) { MatchBox box=(MatchBox) o; if (MainFrame.getInstance().getProject().getSuppressionFilter().isEnabled(box.getMatcher())) needsRebuild=true; MainFrame.getInstance().getProject().getSuppressionFilter().removeChild(box.getMatcher()); } FilterActivity.notifyListeners(FilterListener.Action.UNFILTERING, null); MainFrame.getInstance().setProjectChanged(true); updateFilterPanel(); } }); gbc.gridy = 2; gbc.weighty = 0; gbc.insets = new Insets(5, 0, 0, 0); filterPanel.add(removeAllButton, gbc); removeAllButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { boolean needsRebuild=false; Filter suppressionFilter = MainFrame.getInstance().getProject().getSuppressionFilter(); if (!suppressionFilter.isEmpty()) needsRebuild=true; suppressionFilter.clear(); if (needsRebuild)//TODO This will rebuild even if all the filters being cleared were disabled FilterActivity.notifyListeners(FilterListener.Action.UNFILTERING, null); MainFrame.getInstance().setProjectChanged(true); updateFilterPanel(); } }); gbc.gridy = 3; gbc.weighty = 1; gbc.insets = new Insets(0, 0, 0, 0); filterPanel.add(Box.createGlue(), gbc); return filterPanel; } private static class MatchBox extends JCheckBox{ Matcher m; MatchBox(String text, Matcher m){ super(text); this.m=m; } Matcher getMatcher(){return m;} } void updateFilterPanel() { ArrayList<MatchBox> boxes = new ArrayList<MatchBox>(); final Filter f = MainFrame.getInstance().getProject().getSuppressionFilter(); for(Iterator<Matcher> i = f.childIterator(); i.hasNext(); ) { final Matcher m = i.next(); MatchBox box = new MatchBox(m.toString(),m); box.addItemListener(new ItemListener(){ public void itemStateChanged(ItemEvent evt) { boolean isSelected = ((JCheckBox) evt.getSource()).isSelected(); boolean wasSelected = f.isEnabled(m); if (isSelected == wasSelected) return; f.setEnabled(m, isSelected); FilterActivity.notifyListeners(isSelected ? FilterListener.Action.FILTERING : FilterListener.Action.UNFILTERING, null); MainFrame.getInstance().updateStatusBar(); MainFrame.getInstance().setProjectChanged(true); }}); box.setSelected(f.isEnabled(m)); boxes.add(box); } filterCheckBoxList.setListData(boxes.toArray(new MatchBox[boxes.size()])); } private static class UneditableTableModel extends DefaultTableModel { public UneditableTableModel(Object[][] tableData, String[] strings) { super(tableData,strings); } @Override public boolean isCellEditable(int x, int y) { return false; } } private static class FilterCheckBoxListener implements ItemListener { FilterMatcher filter; FilterCheckBoxListener(FilterMatcher filter) { this.filter = filter; } public void itemStateChanged(ItemEvent evt) { // RebuildThreadMonitor.waitForRebuild(); filter.setActive(((JCheckBox) evt.getSource()).isSelected()); MainFrame.getInstance().updateStatusBar(); MainFrame.getInstance().setProjectChanged(true); } } void freeze() { frozen=true; filterCheckBoxList.setEnabled(false); addButton.setEnabled(false); removeButton.setEnabled(false); } void thaw() { filterCheckBoxList.setEnabled(true); addButton.setEnabled(true); removeButton.setEnabled(true); frozen=false; } void setSelectedTab(int index) { if(index > 0 && index <= mainTabPane.getTabCount()) mainTabPane.setSelectedIndex(index); } }