1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric (at) 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 */ 21 package proguard.gui; 22 23 import proguard.*; 24 import proguard.classfile.ClassConstants; 25 import proguard.classfile.util.ClassUtil; 26 27 import javax.swing.*; 28 import java.awt.*; 29 import java.awt.event.*; 30 import java.util.*; 31 import java.util.List; 32 33 34 /** 35 * This <code>ListPanel</code> allows the user to add, edit, move, and remove 36 * MemberSpecification entries in a list. 37 * 38 * @author Eric Lafortune 39 */ 40 final class MemberSpecificationsPanel extends ListPanel 41 { 42 private final MemberSpecificationDialog fieldSpecificationDialog; 43 private final MemberSpecificationDialog methodSpecificationDialog; 44 45 46 public MemberSpecificationsPanel(JDialog owner, boolean fullKeepOptions) 47 { 48 super(); 49 50 super.firstSelectionButton = fullKeepOptions ? 3 : 2; 51 52 list.setCellRenderer(new MyListCellRenderer()); 53 54 fieldSpecificationDialog = new MemberSpecificationDialog(owner, true); 55 methodSpecificationDialog = new MemberSpecificationDialog(owner, false); 56 57 if (fullKeepOptions) 58 { 59 addAddFieldButton(); 60 } 61 addAddMethodButton(); 62 addEditButton(); 63 addRemoveButton(); 64 addUpButton(); 65 addDownButton(); 66 67 enableSelectionButtons(); 68 } 69 70 71 protected void addAddFieldButton() 72 { 73 JButton addFieldButton = new JButton(msg("addField")); 74 addFieldButton.addActionListener(new ActionListener() 75 { 76 public void actionPerformed(ActionEvent e) 77 { 78 fieldSpecificationDialog.setMemberSpecification(new MemberSpecification()); 79 int returnValue = fieldSpecificationDialog.showDialog(); 80 if (returnValue == MemberSpecificationDialog.APPROVE_OPTION) 81 { 82 // Add the new element. 83 addElement(new MyMemberSpecificationWrapper(fieldSpecificationDialog.getMemberSpecification(), 84 true)); 85 } 86 } 87 }); 88 89 addButton(tip(addFieldButton, "addFieldTip")); 90 } 91 92 93 protected void addAddMethodButton() 94 { 95 JButton addMethodButton = new JButton(msg("addMethod")); 96 addMethodButton.addActionListener(new ActionListener() 97 { 98 public void actionPerformed(ActionEvent e) 99 { 100 methodSpecificationDialog.setMemberSpecification(new MemberSpecification()); 101 int returnValue = methodSpecificationDialog.showDialog(); 102 if (returnValue == MemberSpecificationDialog.APPROVE_OPTION) 103 { 104 // Add the new element. 105 addElement(new MyMemberSpecificationWrapper(methodSpecificationDialog.getMemberSpecification(), 106 false)); 107 } 108 } 109 }); 110 111 addButton(tip(addMethodButton, "addMethodTip")); 112 } 113 114 115 protected void addEditButton() 116 { 117 JButton editButton = new JButton(msg("edit")); 118 editButton.addActionListener(new ActionListener() 119 { 120 public void actionPerformed(ActionEvent e) 121 { 122 MyMemberSpecificationWrapper wrapper = 123 (MyMemberSpecificationWrapper)list.getSelectedValue(); 124 125 MemberSpecificationDialog memberSpecificationDialog = 126 wrapper.isField ? 127 fieldSpecificationDialog : 128 methodSpecificationDialog; 129 130 memberSpecificationDialog.setMemberSpecification(wrapper.memberSpecification); 131 int returnValue = memberSpecificationDialog.showDialog(); 132 if (returnValue == MemberSpecificationDialog.APPROVE_OPTION) 133 { 134 // Replace the old element. 135 wrapper.memberSpecification = memberSpecificationDialog.getMemberSpecification(); 136 setElementAt(wrapper, 137 list.getSelectedIndex()); 138 } 139 } 140 }); 141 142 addButton(tip(editButton, "editTip")); 143 } 144 145 146 /** 147 * Sets the MemberSpecification instances to be represented in this panel. 148 */ 149 public void setMemberSpecifications(List fieldSpecifications, 150 List methodSpecifications) 151 { 152 listModel.clear(); 153 154 if (fieldSpecifications != null) 155 { 156 for (int index = 0; index < fieldSpecifications.size(); index++) 157 { 158 listModel.addElement( 159 new MyMemberSpecificationWrapper((MemberSpecification)fieldSpecifications.get(index), 160 true)); 161 } 162 } 163 164 if (methodSpecifications != null) 165 { 166 for (int index = 0; index < methodSpecifications.size(); index++) 167 { 168 listModel.addElement( 169 new MyMemberSpecificationWrapper((MemberSpecification)methodSpecifications.get(index), 170 false)); 171 } 172 } 173 174 // Make sure the selection buttons are properly enabled, 175 // since the clear method doesn't seem to notify the listener. 176 enableSelectionButtons(); 177 } 178 179 180 /** 181 * Returns the MemberSpecification instances currently represented in 182 * this panel, referring to fields or to methods. 183 * 184 * @param isField specifies whether specifications referring to fields or 185 * specifications referring to methods should be returned. 186 */ 187 public List getMemberSpecifications(boolean isField) 188 { 189 int size = listModel.size(); 190 if (size == 0) 191 { 192 return null; 193 } 194 195 List memberSpecifications = new ArrayList(size); 196 for (int index = 0; index < size; index++) 197 { 198 MyMemberSpecificationWrapper wrapper = 199 (MyMemberSpecificationWrapper)listModel.get(index); 200 201 if (wrapper.isField == isField) 202 { 203 memberSpecifications.add(wrapper.memberSpecification); 204 } 205 } 206 207 return memberSpecifications; 208 } 209 210 211 /** 212 * This ListCellRenderer renders MemberSpecification objects. 213 */ 214 private static class MyListCellRenderer implements ListCellRenderer 215 { 216 private final JLabel label = new JLabel(); 217 218 219 // Implementations for ListCellRenderer. 220 221 public Component getListCellRendererComponent(JList list, 222 Object value, 223 int index, 224 boolean isSelected, 225 boolean cellHasFocus) 226 { 227 MyMemberSpecificationWrapper wrapper = (MyMemberSpecificationWrapper)value; 228 229 MemberSpecification option = wrapper.memberSpecification; 230 String name = option.name; 231 String descriptor = option.descriptor; 232 233 label.setText(wrapper.isField ? 234 (descriptor == null ? name == null ? 235 "<fields>" : 236 "***" + ' ' + name : 237 ClassUtil.externalFullFieldDescription(0, 238 name == null ? "*" : name, 239 descriptor)) : 240 (descriptor == null ? name == null ? 241 "<methods>" : 242 "***" + ' ' + name + "(...)" : 243 ClassUtil.externalFullMethodDescription(ClassConstants.INTERNAL_METHOD_NAME_INIT, 244 0, 245 name == null ? "*" : name, 246 descriptor))); 247 248 if (isSelected) 249 { 250 label.setBackground(list.getSelectionBackground()); 251 label.setForeground(list.getSelectionForeground()); 252 } 253 else 254 { 255 label.setBackground(list.getBackground()); 256 label.setForeground(list.getForeground()); 257 } 258 259 label.setOpaque(true); 260 261 return label; 262 } 263 } 264 265 266 /** 267 * Attaches the tool tip from the GUI resources that corresponds to the 268 * given key, to the given component. 269 */ 270 private static JComponent tip(JComponent component, String messageKey) 271 { 272 component.setToolTipText(msg(messageKey)); 273 274 return component; 275 } 276 277 278 /** 279 * Returns the message from the GUI resources that corresponds to the given 280 * key. 281 */ 282 private static String msg(String messageKey) 283 { 284 return GUIResources.getMessage(messageKey); 285 } 286 287 288 /** 289 * This class wraps a MemberSpecification, additionally storing whether 290 * the option refers to a field or to a method. 291 */ 292 private static class MyMemberSpecificationWrapper 293 { 294 public MemberSpecification memberSpecification; 295 public final boolean isField; 296 297 public MyMemberSpecificationWrapper(MemberSpecification memberSpecification, 298 boolean isField) 299 { 300 this.memberSpecification = memberSpecification; 301 this.isField = isField; 302 } 303 } 304 } 305