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 javax.swing.*; 24 import javax.swing.event.*; 25 import java.awt.*; 26 import java.awt.event.*; 27 import java.util.*; 28 import java.util.List; 29 30 /** 31 * This <code>Jpanel</code> allows the user to move and remove entries in a 32 * list and between lists. Extensions of this class should add buttons to add 33 * and possibly edit entries, and to set and get the resulting list. 34 * 35 * @author Eric Lafortune 36 */ 37 abstract class ListPanel extends JPanel 38 { 39 protected final DefaultListModel listModel = new DefaultListModel(); 40 protected final JList list = new JList(listModel); 41 42 protected int firstSelectionButton = 2; 43 44 ListPanel()45 protected ListPanel() 46 { 47 GridBagLayout layout = new GridBagLayout(); 48 setLayout(layout); 49 50 GridBagConstraints listConstraints = new GridBagConstraints(); 51 listConstraints.gridheight = GridBagConstraints.REMAINDER; 52 listConstraints.fill = GridBagConstraints.BOTH; 53 listConstraints.weightx = 1.0; 54 listConstraints.weighty = 1.0; 55 listConstraints.anchor = GridBagConstraints.NORTHWEST; 56 listConstraints.insets = new Insets(0, 2, 0, 2); 57 58 // Make sure some buttons are disabled or enabled depending on whether 59 // the selection is empty or not. 60 list.addListSelectionListener(new ListSelectionListener() 61 { 62 public void valueChanged(ListSelectionEvent e) 63 { 64 enableSelectionButtons(); 65 } 66 }); 67 68 add(new JScrollPane(list), listConstraints); 69 70 // something like the following calls are up to the extending class: 71 //addAddButton(); 72 //addEditButton(); 73 //addRemoveButton(); 74 //addUpButton(); 75 //addDownButton(); 76 // 77 //enableSelectionButtons(); 78 } 79 80 addRemoveButton()81 protected void addRemoveButton() 82 { 83 JButton removeButton = new JButton(msg("remove")); 84 removeButton.addActionListener(new ActionListener() 85 { 86 public void actionPerformed(ActionEvent e) 87 { 88 // Remove the selected elements. 89 removeElementsAt(list.getSelectedIndices()); 90 } 91 }); 92 93 addButton(tip(removeButton, "removeTip")); 94 } 95 96 addUpButton()97 protected void addUpButton() 98 { 99 JButton upButton = new JButton(msg("moveUp")); 100 upButton.addActionListener(new ActionListener() 101 { 102 public void actionPerformed(ActionEvent e) 103 { 104 int[] selectedIndices = list.getSelectedIndices(); 105 if (selectedIndices.length > 0 && 106 selectedIndices[0] > 0) 107 { 108 // Move the selected elements up. 109 moveElementsAt(selectedIndices, -1); 110 } 111 } 112 }); 113 114 addButton(tip(upButton, "moveUpTip")); 115 } 116 117 addDownButton()118 protected void addDownButton() 119 { 120 JButton downButton = new JButton(msg("moveDown")); 121 downButton.addActionListener(new ActionListener() 122 { 123 public void actionPerformed(ActionEvent e) 124 { 125 int[] selectedIndices = list.getSelectedIndices(); 126 if (selectedIndices.length > 0 && 127 selectedIndices[selectedIndices.length-1] < listModel.getSize()-1) 128 { 129 // Move the selected elements down. 130 moveElementsAt(selectedIndices, 1); 131 } 132 } 133 }); 134 135 addButton(tip(downButton, "moveDownTip")); 136 } 137 138 139 /** 140 * Adds a button that allows to copy or move entries to another ListPanel. 141 * 142 * @param buttonTextKey the button text key. 143 * @param tipKey the tool tip key. 144 * @param panel the other ListPanel. 145 */ addCopyToPanelButton(String buttonTextKey, String tipKey, final ListPanel panel)146 public void addCopyToPanelButton(String buttonTextKey, 147 String tipKey, 148 final ListPanel panel) 149 { 150 JButton moveButton = new JButton(msg(buttonTextKey)); 151 moveButton.addActionListener(new ActionListener() 152 { 153 public void actionPerformed(ActionEvent e) 154 { 155 int[] selectedIndices = list.getSelectedIndices(); 156 Object[] selectedElements = list.getSelectedValues(); 157 158 // Remove the selected elements from this panel. 159 removeElementsAt(selectedIndices); 160 161 // Add the elements to the other panel. 162 panel.addElements(selectedElements); 163 } 164 }); 165 166 addButton(tip(moveButton, tipKey)); 167 } 168 169 addButton(JComponent button)170 protected void addButton(JComponent button) 171 { 172 GridBagConstraints buttonConstraints = new GridBagConstraints(); 173 buttonConstraints.gridwidth = GridBagConstraints.REMAINDER; 174 buttonConstraints.fill = GridBagConstraints.HORIZONTAL; 175 buttonConstraints.anchor = GridBagConstraints.NORTHWEST; 176 buttonConstraints.insets = new Insets(0, 2, 0, 2); 177 178 add(button, buttonConstraints); 179 } 180 181 182 /** 183 * Returns a list of all right-hand side buttons. 184 */ getButtons()185 public List getButtons() 186 { 187 List list = new ArrayList(getComponentCount()-1); 188 189 // Add all buttons. 190 for (int index = 1; index < getComponentCount(); index++) 191 { 192 list.add(getComponent(index)); 193 } 194 195 return list; 196 } 197 198 addElement(Object element)199 protected void addElement(Object element) 200 { 201 listModel.addElement(element); 202 203 // Make sure it is selected. 204 list.setSelectedIndex(listModel.size() - 1); 205 } 206 207 addElements(Object[] elements)208 protected void addElements(Object[] elements) 209 { 210 // Add the elements one by one. 211 for (int index = 0; index < elements.length; index++) 212 { 213 listModel.addElement(elements[index]); 214 } 215 216 // Make sure they are selected. 217 int[] selectedIndices = new int[elements.length]; 218 for (int index = 0; index < selectedIndices.length; index++) 219 { 220 selectedIndices[index] = 221 listModel.size() - selectedIndices.length + index; 222 } 223 list.setSelectedIndices(selectedIndices); 224 } 225 226 moveElementsAt(int[] indices, int offset)227 protected void moveElementsAt(int[] indices, int offset) 228 { 229 // Remember the selected elements. 230 Object[] selectedElements = list.getSelectedValues(); 231 232 // Remove the selected elements. 233 removeElementsAt(indices); 234 235 // Update the element indices. 236 for (int index = 0; index < indices.length; index++) 237 { 238 indices[index] += offset; 239 } 240 241 // Reinsert the selected elements. 242 insertElementsAt(selectedElements, indices); 243 } 244 245 insertElementsAt(Object[] elements, int[] indices)246 protected void insertElementsAt(Object[] elements, int[] indices) 247 { 248 for (int index = 0; index < elements.length; index++) 249 { 250 listModel.insertElementAt(elements[index], indices[index]); 251 } 252 253 // Make sure they are selected. 254 list.setSelectedIndices(indices); 255 } 256 257 setElementAt(Object element, int index)258 protected void setElementAt(Object element, int index) 259 { 260 listModel.setElementAt(element, index); 261 262 // Make sure it is selected. 263 list.setSelectedIndex(index); 264 } 265 266 setElementsAt(Object[] elements, int[] indices)267 protected void setElementsAt(Object[] elements, int[] indices) 268 { 269 for (int index = 0; index < elements.length; index++) 270 { 271 listModel.setElementAt(elements[index], indices[index]); 272 } 273 274 // Make sure they are selected. 275 list.setSelectedIndices(indices); 276 } 277 278 removeElementsAt(int[] indices)279 protected void removeElementsAt(int[] indices) 280 { 281 for (int index = indices.length - 1; index >= 0; index--) 282 { 283 listModel.removeElementAt(indices[index]); 284 } 285 286 // Make sure nothing is selected. 287 list.clearSelection(); 288 289 // Make sure the selection buttons are properly enabled, 290 // since the above method doesn't seem to notify the listener. 291 enableSelectionButtons(); 292 } 293 294 removeAllElements()295 protected void removeAllElements() 296 { 297 listModel.removeAllElements(); 298 299 // Make sure the selection buttons are properly enabled, 300 // since the above method doesn't seem to notify the listener. 301 enableSelectionButtons(); 302 } 303 304 305 /** 306 * Enables or disables the buttons that depend on a selection. 307 */ enableSelectionButtons()308 protected void enableSelectionButtons() 309 { 310 boolean selected = !list.isSelectionEmpty(); 311 312 // Loop over all components, except the list itself and the Add button. 313 for (int index = firstSelectionButton; index < getComponentCount(); index++) 314 { 315 getComponent(index).setEnabled(selected); 316 } 317 } 318 319 320 /** 321 * Attaches the tool tip from the GUI resources that corresponds to the 322 * given key, to the given component. 323 */ tip(JComponent component, String messageKey)324 private static JComponent tip(JComponent component, String messageKey) 325 { 326 component.setToolTipText(msg(messageKey)); 327 328 return component; 329 } 330 331 332 /** 333 * Returns the message from the GUI resources that corresponds to the given 334 * key. 335 */ msg(String messageKey)336 private static String msg(String messageKey) 337 { 338 return GUIResources.getMessage(messageKey); 339 } 340 } 341