/*
* $Id$
*
* Copyright (c) 2006 by Rodney Kinney
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.configure;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import VASSAL.tools.SequenceEncoder;
/**
* Configures a variable-length list of objects
*
* @author rkinney
*
*/
public abstract class ListConfigurer extends Configurer implements
PropertyChangeListener {
protected Box controls;
protected Box configControls;
protected JPanel panel;
protected Dimension fixedSize;
protected List<Configurer> configurers = new ArrayList<Configurer>();
public ListConfigurer(String key, String name) {
super(key, name, new ArrayList<Object>());
}
public ListConfigurer(String key, String name, List<?> val) {
super(key, name, val);
}
public String getValueString() {
if (getListValue().isEmpty()) {
return "";
}
Configurer c = buildChildConfigurer();
SequenceEncoder se = new SequenceEncoder(',');
for (Object value : getListValue()) {
c.setValue(value);
se.append(c.getValueString());
}
return se.getValue();
}
public void setValue(String s) {
getListValue().clear();
if (s.length() > 0) {
Configurer c = buildChildConfigurer();
SequenceEncoder.Decoder sd = new SequenceEncoder.Decoder(s, ',');
while (sd.hasMoreTokens()) {
c.setValue(sd.nextToken());
getListValue().add(c.getValue());
}
}
updateControls();
}
protected void updateValue() {
noUpdate = true;
ArrayList<Object> newArray = new ArrayList<Object>();
for (Configurer c : configurers) {
newArray.add(c.getValue());
}
setValue(newArray);
noUpdate = false;
}
public void setValue(Object o) {
if (o == null) {
o = new ArrayList<Object>();
}
super.setValue(o);
if (!noUpdate) {
updateControls();
}
}
public Component getControls() {
if (panel == null) {
panel = new JPanel(new BorderLayout());
controls = Box.createVerticalBox();
final JScrollPane scroll = new JScrollPane(controls);
controls.setBorder(BorderFactory.createTitledBorder(getName()));
configControls = Box.createVerticalBox();
JButton addButton = new JButton("New");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Configurer c = buildChildConfigurer();
getListValue().add(c.getValue());
updateControls();
}
});
controls.add(addButton);
controls.add(configControls);
panel.add(scroll, BorderLayout.CENTER);
updateControls();
}
return panel;
}
@SuppressWarnings("unchecked")
public List<Object> getListValue() {
return (List<Object>) getValue();
}
/**
* The objects in the list are specified by the Configurer returned here
*
* @return
*/
protected abstract Configurer buildChildConfigurer();
public void propertyChange(PropertyChangeEvent evt) {
updateValue();
}
protected void updateControls() {
if (controls != null) {
for (Configurer c : configurers) {
c.removePropertyChangeListener(this);
}
configurers.clear();
configControls.removeAll();
for (Object value : getListValue()) {
final Configurer c = buildChildConfigurer();
c.setValue(value);
c.addPropertyChangeListener(this);
configurers.add(c);
final Box b = Box.createHorizontalBox();
JButton delButton = new JButton("Remove");
delButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getListValue().remove(c.getValue());
updateControls();
repack();
}
});
b.add(delButton);
b.add(c.getControls());
configControls.add(b);
if (configurers.size() > 5) {
if (fixedSize == null) {
fixedSize = new Dimension(
panel.getPreferredSize().width + 20, 210);
}
panel.setPreferredSize(fixedSize);
}
else {
panel.setPreferredSize(null);
}
}
repack();
}
}
public void repack() {
Window w = SwingUtilities.getWindowAncestor(controls);
if (w != null) {
w.pack();
}
}
@Override
public int hashCode() {
String valueString = getValueString();
final int prime = 31;
int result = 1;
result = prime * result
+ ((valueString == null) ? 0 : valueString.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ListConfigurer other = (ListConfigurer) obj;
String valueString = getValueString();
String otherValueString = other.getValueString();
if (valueString == null) {
if (otherValueString != null)
return false;
} else if (!valueString.equals(otherValueString))
return false;
return true;
}
}