/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import com.servoy.j2db.smart.J2DBClient;
public class MultiSelectionPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private boolean hasUpDownButtons;
private JList sourceList;
private JList targetList;
private DefaultListModel sourceModel = new DefaultListModel();
private DefaultListModel targetModel = new DefaultListModel();
private IndexedObject[] entryList;
public MultiSelectionPanel(Object[] entries, boolean[] isSelected, int[] targetListIndices, String message,
String label1, String label2, boolean hasUpDownButtons)
{
super();
this.hasUpDownButtons = hasUpDownButtons;
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder());
final JButton downButton = new JButton("Down"); //$NON-NLS-1$
Dimension minimumSize = downButton.getPreferredSize();// new
// Dimension(100,20);
final JButton addButton = new JButton(" >> "); //$NON-NLS-1$
addButton.addActionListener(this);
addButton.setActionCommand("add"); //$NON-NLS-1$
addButton.setPreferredSize(minimumSize);
addButton.setMinimumSize(minimumSize);
addButton.setMaximumSize(minimumSize);
final JButton removeButton = new JButton(" << "); //$NON-NLS-1$
removeButton.addActionListener(this);
removeButton.setActionCommand("remove"); //$NON-NLS-1$
removeButton.setPreferredSize(minimumSize);
removeButton.setMinimumSize(minimumSize);
removeButton.setMaximumSize(minimumSize);
JPanel movePane = new JPanel();
movePane.setLayout(new BoxLayout(movePane, BoxLayout.Y_AXIS));
movePane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
movePane.setMaximumSize(new Dimension(150, 200));
movePane.add(Box.createVerticalGlue());
movePane.add(addButton);
movePane.add(Box.createRigidArea(new Dimension(0, J2DBClient.BUTTON_SPACING)));
movePane.add(removeButton);
movePane.add(Box.createVerticalGlue());
JPanel sourcePane = new JPanel();
sourcePane.setLayout(new BorderLayout());
if (label1 != null)
{
JLabel sourceLabel = new JLabel(label1);
sourceLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
sourcePane.add(sourceLabel, BorderLayout.NORTH);
}
JPanel targetPane = new JPanel();
targetPane.setLayout(new BorderLayout());
if (label2 != null)
{
JLabel targetLabel = new JLabel(label2);
targetLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
targetPane.add(targetLabel, BorderLayout.NORTH);
}
sourceList = new JList(sourceModel);
JScrollPane sourceScrollPane = new JScrollPane(sourceList);
sourceScrollPane.setPreferredSize(new Dimension(200, 150));
sourcePane.add(sourceScrollPane, BorderLayout.CENTER);
sourceList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
if (MultiSelectionPanel.this.hasUpDownButtons)
add(); // order matters in target
else move(sourceList, targetList); // keep standard order
}
}
});
targetList = new JList(targetModel);
JScrollPane targetScrollPane = new JScrollPane(targetList);
targetScrollPane.setPreferredSize(new Dimension(200, 150));
targetPane.add(targetScrollPane, BorderLayout.CENTER);
targetList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
move(targetList, sourceList);
}
}
});
JPanel listPane = new JPanel(new BorderLayout());
listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS));
listPane.add(sourcePane);
listPane.add(movePane);
listPane.add(targetPane);
if (hasUpDownButtons)
{
JPanel upDownPane = new JPanel();
upDownPane.setLayout(new BoxLayout(upDownPane, BoxLayout.Y_AXIS));
upDownPane.setMaximumSize(new Dimension(150, 200));
JButton upButton = new JButton("Up"); //$NON-NLS-1$
upButton.addActionListener(this);
upButton.setActionCommand("up"); //$NON-NLS-1$
upButton.setPreferredSize(minimumSize);
upButton.setMinimumSize(minimumSize);
upButton.setMaximumSize(minimumSize);
upButton.setMnemonic(KeyEvent.VK_U);
upDownPane.add(Box.createVerticalGlue());
upDownPane.add(upButton);
upDownPane.add(Box.createRigidArea(new Dimension(0, J2DBClient.BUTTON_SPACING)));
downButton.addActionListener(this);
downButton.setActionCommand("down"); //$NON-NLS-1$
downButton.setPreferredSize(minimumSize);
downButton.setMinimumSize(minimumSize);
downButton.setMaximumSize(minimumSize);
downButton.setMnemonic(KeyEvent.VK_D);
upDownPane.add(downButton);
upDownPane.add(Box.createVerticalGlue());
upDownPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
listPane.add(upDownPane);
}
if (message != null)
{
JPanel messagePane = new JPanel();
messagePane.setLayout(new BoxLayout(messagePane, BoxLayout.X_AXIS));
messagePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
messagePane.add(new JLabel(message));
messagePane.add(Box.createHorizontalGlue());
add(messagePane, BorderLayout.NORTH);
}
add(listPane, BorderLayout.CENTER);
setData(entries, isSelected, targetListIndices);
}
public void setData(Object[] entries, boolean[] isSelected, int[] targetListIndices)
{
sourceModel.clear();
targetModel.clear();
entryList = new IndexedObject[entries.length];
for (int i = 0; i < entries.length; i++)
{
entryList[i] = new IndexedObject(i, entries[i]);
}
targetListIndices = targetListIndices == null ? new int[0] : ((int[]) targetListIndices.clone());
if (!hasUpDownButtons)
Arrays.sort(targetListIndices);
entries = (Object[]) entries.clone();
for (int i = 0; i < targetListIndices.length; i++)
{
int index = targetListIndices[i];
targetModel.addElement(entryList[index]);
if (isSelected != null && isSelected[index])
targetList.addSelectionInterval(i, i);
entries[index] = null;
}
for (int i = 0, j = 0; i < entries.length; i++)
{
if (entries[i] != null)
{
sourceModel.addElement(entryList[i]);
if (isSelected != null && isSelected[i])
sourceList.addSelectionInterval(j, j);
j++;
}
}
}
private void add()
{
int targetLength = targetModel.getSize();
int[] selected = sourceList.getSelectedIndices();
if (selected.length > 0)
{
Arrays.sort(selected);
sourceList.clearSelection();
targetList.clearSelection();
int j = 0;
for (int i = 0; i < selected.length; i++)
{
Object object = sourceModel.remove(selected[i] - j++);
targetModel.addElement(object);
}
targetList.addSelectionInterval(targetLength, targetLength + selected.length - 1);
}
}
private void move(JList sourceList, JList targetList)
{
DefaultListModel sourceModel = (DefaultListModel) sourceList.getModel();
DefaultListModel targetModel = (DefaultListModel) targetList.getModel();
int[] selected = sourceList.getSelectedIndices();
if (selected.length > 0)
{
sourceList.clearSelection();
int[] targetIndices = new int[targetModel.size() + selected.length];
int k = 0;
Enumeration enumeration = targetModel.elements();
while (enumeration.hasMoreElements())
{
IndexedObject object = (IndexedObject) enumeration.nextElement();
targetIndices[k++] = object.getIndex();
}
for (int i = selected.length - 1; i >= 0; i--)
{
IndexedObject object = (IndexedObject) sourceModel.remove(selected[i]);
targetIndices[k++] = selected[i] = object.getIndex();
}
Arrays.sort(targetIndices);
Arrays.sort(selected);
k = 0;
targetModel.clear();
for (int i = 0; i < targetIndices.length; i++)
{
targetModel.addElement(entryList[targetIndices[i]]);
if (k < selected.length && selected[k] == targetIndices[k])
{
selected[k++] = i;
}
}
targetList.setSelectedIndices(selected);
}
}
private void up()
{
int[] selected = targetList.getSelectedIndices();
if (selected.length > 0)
{
Arrays.sort(selected);
if (selected[0] > 0)
{
for (int i = 0; i < selected.length; i++)
{
Object object = targetModel.remove(selected[i]);
selected[i]--;
targetModel.add(selected[i], object);
}
targetList.setSelectedIndices(selected);
}
}
}
private void down()
{
int[] selected = targetList.getSelectedIndices();
if (selected.length > 0)
{
Arrays.sort(selected);
if (selected[selected.length - 1] < targetModel.size() - 1)
{
for (int i = selected.length - 1; i >= 0; i--)
{
Object object = targetModel.remove(selected[i]);
selected[i]++;
targetModel.add(selected[i], object);
}
targetList.setSelectedIndices(selected);
}
}
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
if ("add".equals(command)) //$NON-NLS-1$
{
if (hasUpDownButtons)
add(); // order matters in target
else move(sourceList, targetList); // keep standard order
}
else if ("remove".equals(command)) //$NON-NLS-1$
move(targetList, sourceList);
else if ("up".equals(command)) //$NON-NLS-1$
up();
else if ("down".equals(command)) //$NON-NLS-1$
down();
}
public int[] getSelectedValues()
{
int[] selection = new int[targetModel.size()];
Enumeration elements = targetModel.elements();
int i = 0;
while (elements.hasMoreElements())
{
IndexedObject element = (IndexedObject) elements.nextElement();
selection[i++] = element.getIndex();
}
return selection;
}
}