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