1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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 */ 21 package proguard.gui; 22 23 import proguard.MemberSpecification; 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 MemberSpecificationsPanel(JDialog owner, boolean fullKeepOptions)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 addAddFieldButton()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 addAddMethodButton()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 addEditButton()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 */ setMemberSpecifications(List fieldSpecifications, List methodSpecifications)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 */ getMemberSpecifications(boolean isField)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 getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)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.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 */ tip(JComponent component, String messageKey)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 */ msg(String messageKey)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 MyMemberSpecificationWrapper(MemberSpecification memberSpecification, boolean isField)297 public MyMemberSpecificationWrapper(MemberSpecification memberSpecification, 298 boolean isField) 299 { 300 this.memberSpecification = memberSpecification; 301 this.isField = isField; 302 } 303 } 304 } 305