/*
|
* ProGuard -- shrinking, optimization, obfuscation, and preverification
|
* of Java bytecode.
|
*
|
* Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of the GNU General Public License as published by the Free
|
* Software Foundation; either version 2 of the License, or (at your option)
|
* any later version.
|
*
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* more details.
|
*
|
* You should have received a copy of the GNU General Public License along
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
*/
|
package proguard.gui;
|
|
import javax.swing.*;
|
import javax.swing.event.*;
|
import java.awt.*;
|
import java.awt.event.*;
|
import java.util.*;
|
import java.util.List;
|
|
/**
|
* This <code>Jpanel</code> allows the user to move and remove entries in a
|
* list and between lists. Extensions of this class should add buttons to add
|
* and possibly edit entries, and to set and get the resulting list.
|
*
|
* @author Eric Lafortune
|
*/
|
abstract class ListPanel extends JPanel
|
{
|
protected final DefaultListModel listModel = new DefaultListModel();
|
protected final JList list = new JList(listModel);
|
|
protected int firstSelectionButton = 2;
|
|
|
protected ListPanel()
|
{
|
GridBagLayout layout = new GridBagLayout();
|
setLayout(layout);
|
|
GridBagConstraints listConstraints = new GridBagConstraints();
|
listConstraints.gridheight = GridBagConstraints.REMAINDER;
|
listConstraints.fill = GridBagConstraints.BOTH;
|
listConstraints.weightx = 1.0;
|
listConstraints.weighty = 1.0;
|
listConstraints.anchor = GridBagConstraints.NORTHWEST;
|
listConstraints.insets = new Insets(0, 2, 0, 2);
|
|
// Make sure some buttons are disabled or enabled depending on whether
|
// the selection is empty or not.
|
list.addListSelectionListener(new ListSelectionListener()
|
{
|
public void valueChanged(ListSelectionEvent e)
|
{
|
enableSelectionButtons();
|
}
|
});
|
|
add(new JScrollPane(list), listConstraints);
|
|
// something like the following calls are up to the extending class:
|
//addAddButton();
|
//addEditButton();
|
//addRemoveButton();
|
//addUpButton();
|
//addDownButton();
|
//
|
//enableSelectionButtons();
|
}
|
|
|
protected void addRemoveButton()
|
{
|
JButton removeButton = new JButton(msg("remove"));
|
removeButton.addActionListener(new ActionListener()
|
{
|
public void actionPerformed(ActionEvent e)
|
{
|
// Remove the selected elements.
|
removeElementsAt(list.getSelectedIndices());
|
}
|
});
|
|
addButton(tip(removeButton, "removeTip"));
|
}
|
|
|
protected void addUpButton()
|
{
|
JButton upButton = new JButton(msg("moveUp"));
|
upButton.addActionListener(new ActionListener()
|
{
|
public void actionPerformed(ActionEvent e)
|
{
|
int[] selectedIndices = list.getSelectedIndices();
|
if (selectedIndices.length > 0 &&
|
selectedIndices[0] > 0)
|
{
|
// Move the selected elements up.
|
moveElementsAt(selectedIndices, -1);
|
}
|
}
|
});
|
|
addButton(tip(upButton, "moveUpTip"));
|
}
|
|
|
protected void addDownButton()
|
{
|
JButton downButton = new JButton(msg("moveDown"));
|
downButton.addActionListener(new ActionListener()
|
{
|
public void actionPerformed(ActionEvent e)
|
{
|
int[] selectedIndices = list.getSelectedIndices();
|
if (selectedIndices.length > 0 &&
|
selectedIndices[selectedIndices.length-1] < listModel.getSize()-1)
|
{
|
// Move the selected elements down.
|
moveElementsAt(selectedIndices, 1);
|
}
|
}
|
});
|
|
addButton(tip(downButton, "moveDownTip"));
|
}
|
|
|
/**
|
* Adds a button that allows to copy or move entries to another ListPanel.
|
*
|
* @param buttonTextKey the button text key.
|
* @param tipKey the tool tip key.
|
* @param panel the other ListPanel.
|
*/
|
public void addCopyToPanelButton(String buttonTextKey,
|
String tipKey,
|
final ListPanel panel)
|
{
|
JButton moveButton = new JButton(msg(buttonTextKey));
|
moveButton.addActionListener(new ActionListener()
|
{
|
public void actionPerformed(ActionEvent e)
|
{
|
int[] selectedIndices = list.getSelectedIndices();
|
Object[] selectedElements = list.getSelectedValues();
|
|
// Remove the selected elements from this panel.
|
removeElementsAt(selectedIndices);
|
|
// Add the elements to the other panel.
|
panel.addElements(selectedElements);
|
}
|
});
|
|
addButton(tip(moveButton, tipKey));
|
}
|
|
|
protected void addButton(JComponent button)
|
{
|
GridBagConstraints buttonConstraints = new GridBagConstraints();
|
buttonConstraints.gridwidth = GridBagConstraints.REMAINDER;
|
buttonConstraints.fill = GridBagConstraints.HORIZONTAL;
|
buttonConstraints.anchor = GridBagConstraints.NORTHWEST;
|
buttonConstraints.insets = new Insets(0, 2, 0, 2);
|
|
add(button, buttonConstraints);
|
}
|
|
|
/**
|
* Returns a list of all right-hand side buttons.
|
*/
|
public List getButtons()
|
{
|
List list = new ArrayList(getComponentCount()-1);
|
|
// Add all buttons.
|
for (int index = 1; index < getComponentCount(); index++)
|
{
|
list.add(getComponent(index));
|
}
|
|
return list;
|
}
|
|
|
protected void addElement(Object element)
|
{
|
listModel.addElement(element);
|
|
// Make sure it is selected.
|
list.setSelectedIndex(listModel.size() - 1);
|
}
|
|
|
protected void addElements(Object[] elements)
|
{
|
// Add the elements one by one.
|
for (int index = 0; index < elements.length; index++)
|
{
|
listModel.addElement(elements[index]);
|
}
|
|
// Make sure they are selected.
|
int[] selectedIndices = new int[elements.length];
|
for (int index = 0; index < selectedIndices.length; index++)
|
{
|
selectedIndices[index] =
|
listModel.size() - selectedIndices.length + index;
|
}
|
list.setSelectedIndices(selectedIndices);
|
}
|
|
|
protected void moveElementsAt(int[] indices, int offset)
|
{
|
// Remember the selected elements.
|
Object[] selectedElements = list.getSelectedValues();
|
|
// Remove the selected elements.
|
removeElementsAt(indices);
|
|
// Update the element indices.
|
for (int index = 0; index < indices.length; index++)
|
{
|
indices[index] += offset;
|
}
|
|
// Reinsert the selected elements.
|
insertElementsAt(selectedElements, indices);
|
}
|
|
|
protected void insertElementsAt(Object[] elements, int[] indices)
|
{
|
for (int index = 0; index < elements.length; index++)
|
{
|
listModel.insertElementAt(elements[index], indices[index]);
|
}
|
|
// Make sure they are selected.
|
list.setSelectedIndices(indices);
|
}
|
|
|
protected void setElementAt(Object element, int index)
|
{
|
listModel.setElementAt(element, index);
|
|
// Make sure it is selected.
|
list.setSelectedIndex(index);
|
}
|
|
|
protected void setElementsAt(Object[] elements, int[] indices)
|
{
|
for (int index = 0; index < elements.length; index++)
|
{
|
listModel.setElementAt(elements[index], indices[index]);
|
}
|
|
// Make sure they are selected.
|
list.setSelectedIndices(indices);
|
}
|
|
|
protected void removeElementsAt(int[] indices)
|
{
|
for (int index = indices.length - 1; index >= 0; index--)
|
{
|
listModel.removeElementAt(indices[index]);
|
}
|
|
// Make sure nothing is selected.
|
list.clearSelection();
|
|
// Make sure the selection buttons are properly enabled,
|
// since the above method doesn't seem to notify the listener.
|
enableSelectionButtons();
|
}
|
|
|
protected void removeAllElements()
|
{
|
listModel.removeAllElements();
|
|
// Make sure the selection buttons are properly enabled,
|
// since the above method doesn't seem to notify the listener.
|
enableSelectionButtons();
|
}
|
|
|
/**
|
* Enables or disables the buttons that depend on a selection.
|
*/
|
protected void enableSelectionButtons()
|
{
|
boolean selected = !list.isSelectionEmpty();
|
|
// Loop over all components, except the list itself and the Add button.
|
for (int index = firstSelectionButton; index < getComponentCount(); index++)
|
{
|
getComponent(index).setEnabled(selected);
|
}
|
}
|
|
|
/**
|
* Attaches the tool tip from the GUI resources that corresponds to the
|
* given key, to the given component.
|
*/
|
private static JComponent tip(JComponent component, String messageKey)
|
{
|
component.setToolTipText(msg(messageKey));
|
|
return component;
|
}
|
|
|
/**
|
* Returns the message from the GUI resources that corresponds to the given
|
* key.
|
*/
|
private static String msg(String messageKey)
|
{
|
return GUIResources.getMessage(messageKey);
|
}
|
}
|