1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.gui; 22 23import proguard.optimize.Optimizer; 24import proguard.util.*; 25 26import javax.swing.*; 27import javax.swing.border.*; 28import java.awt.*; 29import java.awt.event.*; 30 31/** 32 * This <code>JDialog</code> allows the user to enter a String. 33 * 34 * @author Eric Lafortune 35 */ 36final class OptimizationsDialog extends JDialog 37{ 38 /** 39 * Return value if the dialog is canceled (with the Cancel button or by 40 * closing the dialog window). 41 */ 42 public static final int CANCEL_OPTION = 1; 43 44 /** 45 * Return value if the dialog is approved (with the Ok button). 46 */ 47 public static final int APPROVE_OPTION = 0; 48 49 50 private final JCheckBox[] optimizationCheckBoxes = new JCheckBox[Optimizer.OPTIMIZATION_NAMES.length]; 51 52 private int returnValue; 53 54 55 public OptimizationsDialog(JFrame owner) 56 { 57 super(owner, msg("selectOptimizations"), true); 58 setResizable(true); 59 60 // Create some constraints that can be reused. 61 GridBagConstraints constraintsLast = new GridBagConstraints(); 62 constraintsLast.gridwidth = GridBagConstraints.REMAINDER; 63 constraintsLast.anchor = GridBagConstraints.WEST; 64 constraintsLast.insets = new Insets(1, 2, 1, 2); 65 66 GridBagConstraints constraintsLastStretch = new GridBagConstraints(); 67 constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER; 68 constraintsLastStretch.fill = GridBagConstraints.HORIZONTAL; 69 constraintsLastStretch.weightx = 1.0; 70 constraintsLastStretch.anchor = GridBagConstraints.WEST; 71 constraintsLastStretch.insets = constraintsLast.insets; 72 73 GridBagConstraints panelConstraints = new GridBagConstraints(); 74 panelConstraints.gridwidth = GridBagConstraints.REMAINDER; 75 panelConstraints.fill = GridBagConstraints.HORIZONTAL; 76 panelConstraints.weightx = 1.0; 77 panelConstraints.weighty = 0.0; 78 panelConstraints.anchor = GridBagConstraints.NORTHWEST; 79 panelConstraints.insets = constraintsLast.insets; 80 81 GridBagConstraints selectButtonConstraints = new GridBagConstraints(); 82 selectButtonConstraints.weighty = 1.0; 83 selectButtonConstraints.anchor = GridBagConstraints.SOUTHWEST; 84 selectButtonConstraints.insets = new Insets(4, 4, 8, 4); 85 86 GridBagConstraints okButtonConstraints = new GridBagConstraints(); 87 okButtonConstraints.weightx = 1.0; 88 okButtonConstraints.weighty = 1.0; 89 okButtonConstraints.anchor = GridBagConstraints.SOUTHEAST; 90 okButtonConstraints.insets = selectButtonConstraints.insets; 91 92 GridBagConstraints cancelButtonConstraints = new GridBagConstraints(); 93 cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER; 94 cancelButtonConstraints.weighty = 1.0; 95 cancelButtonConstraints.anchor = GridBagConstraints.SOUTHEAST; 96 cancelButtonConstraints.insets = selectButtonConstraints.insets; 97 98 GridBagLayout layout = new GridBagLayout(); 99 100 Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED); 101 102 // Create the optimizations panel. 103 JPanel optimizationsPanel = new JPanel(layout); 104 JPanel optimizationSubpanel = null; 105 String lastOptimizationPrefix = null; 106 107 for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++) 108 { 109 String optimizationName = Optimizer.OPTIMIZATION_NAMES[index]; 110 111 String optimizationPrefix = optimizationName.substring(0, optimizationName.indexOf('/')); 112 113 if (optimizationSubpanel == null || !optimizationPrefix.equals(lastOptimizationPrefix)) 114 { 115 // Create a new keep subpanel and add it. 116 optimizationSubpanel = new JPanel(layout); 117 optimizationSubpanel.setBorder(BorderFactory.createTitledBorder(etchedBorder, msg(optimizationPrefix))); 118 optimizationsPanel.add(optimizationSubpanel, panelConstraints); 119 120 lastOptimizationPrefix = optimizationPrefix; 121 } 122 123 JCheckBox optimizationCheckBox = new JCheckBox(optimizationName); 124 optimizationCheckBoxes[index] = optimizationCheckBox; 125 126 optimizationSubpanel.add(tip(optimizationCheckBox, optimizationName.replace('/', '_')+"Tip"), constraintsLastStretch); 127 } 128 129 // Create the Select All button. 130 JButton selectAllButton = new JButton(msg("selectAll")); 131 selectAllButton.addActionListener(new ActionListener() 132 { 133 public void actionPerformed(ActionEvent e) 134 { 135 for (int index = 0; index < optimizationCheckBoxes.length; index++) 136 { 137 optimizationCheckBoxes[index].setSelected(true); 138 } 139 } 140 }); 141 142 // Create the Select All button. 143 JButton selectNoneButton = new JButton(msg("selectNone")); 144 selectNoneButton.addActionListener(new ActionListener() 145 { 146 public void actionPerformed(ActionEvent e) 147 { 148 for (int index = 0; index < optimizationCheckBoxes.length; index++) 149 { 150 optimizationCheckBoxes[index].setSelected(false); 151 } 152 } 153 }); 154 155 // Create the Ok button. 156 JButton okButton = new JButton(msg("ok")); 157 okButton.addActionListener(new ActionListener() 158 { 159 public void actionPerformed(ActionEvent e) 160 { 161 returnValue = APPROVE_OPTION; 162 hide(); 163 } 164 }); 165 166 // Create the Cancel button. 167 JButton cancelButton = new JButton(msg("cancel")); 168 cancelButton.addActionListener(new ActionListener() 169 { 170 public void actionPerformed(ActionEvent e) 171 { 172 hide(); 173 } 174 }); 175 176 // Add all panels to the main panel. 177 optimizationsPanel.add(selectAllButton, selectButtonConstraints); 178 optimizationsPanel.add(selectNoneButton, selectButtonConstraints); 179 optimizationsPanel.add(okButton, okButtonConstraints); 180 optimizationsPanel.add(cancelButton, cancelButtonConstraints); 181 182 getContentPane().add(new JScrollPane(optimizationsPanel)); 183 } 184 185 186 /** 187 * Sets the initial optimization filter to be used by the dialog. 188 */ 189 public void setFilter(String optimizations) 190 { 191 StringMatcher filter = optimizations != null && optimizations.length() > 0 ? 192 new ListParser(new NameParser()).parse(optimizations) : 193 new FixedStringMatcher(""); 194 195 for (int index = 0; index < Optimizer.OPTIMIZATION_NAMES.length; index++) 196 { 197 optimizationCheckBoxes[index].setSelected(filter.matches(Optimizer.OPTIMIZATION_NAMES[index])); 198 } 199 } 200 201 202 /** 203 * Returns the optimization filter composed from the settings in the dialog. 204 */ 205 public String getFilter() 206 { 207 return new FilterBuilder(optimizationCheckBoxes, '/').buildFilter(); 208 } 209 210 211 /** 212 * Shows this dialog. This method only returns when the dialog is closed. 213 * 214 * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>, 215 * depending on the choice of the user. 216 */ 217 public int showDialog() 218 { 219 returnValue = CANCEL_OPTION; 220 221 // Open the dialog in the right place, then wait for it to be closed, 222 // one way or another. 223 pack(); 224 setLocationRelativeTo(getOwner()); 225 show(); 226 227 return returnValue; 228 } 229 230 231 /** 232 * Attaches the tool tip from the GUI resources that corresponds to the 233 * given key, to the given component. 234 */ 235 private static JComponent tip(JComponent component, String messageKey) 236 { 237 component.setToolTipText(msg(messageKey)); 238 239 return component; 240 } 241 242 243 /** 244 * Returns the message from the GUI resources that corresponds to the given 245 * key. 246 */ 247 private static String msg(String messageKey) 248 { 249 return GUIResources.getMessage(messageKey); 250 } 251}