// This file is part of PleoCommand:
// Interactively control Pleo with psychobiological parameters
//
// Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de
//
// 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., 51 Franklin Street, Boston, USA.
package pleocmd.cfg;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.JComboBox;
import pleocmd.Log;
import pleocmd.exc.ConfigurationException;
import pleocmd.exc.InternalException;
import pleocmd.itfc.gui.Layouter;
public class ConfigItem<E> extends ConfigValue {
private final List<String> identifiers = new ArrayList<String>();
private final boolean freeAssign;
private String content;
private JComboBox cb;
private boolean internalMod;
/**
* Creates a new {@link ConfigItem}.
*
* @param label
* name of this {@link ConfigItem} - used in GUI mode
* configuration and for configuration files
* @param freeAssign
* if true any string may be assigned to this {@link ConfigItem},
* if false only the ones in the list of identifiers may be used
* @param identifiers
* list of valid {@link String}s that can be used for this
* {@link ConfigItem} or - if freeAssign is true - a list of
* proposals for GUI mode configuration.
*/
public ConfigItem(final String label, final boolean freeAssign,
final List<E> identifiers) {
super(label);
if (identifiers.isEmpty() && !freeAssign)
throw new IllegalArgumentException("list of identifiers is empty");
try {
for (final E id : identifiers) {
final String idStr = id.toString();
checkValidString(idStr, false);
this.identifiers.add(idStr);
}
} catch (final ConfigurationException e) {
throw new IllegalArgumentException(
"List of identifiers is invalid", e);
}
this.freeAssign = freeAssign;
if (!identifiers.isEmpty()) setContentIndex(0);
}
public ConfigItem(final String label, final String content,
final List<E> identifiers) {
this(label, true, identifiers);
try {
setContent(content);
} catch (final ConfigurationException e) {
throw new InternalException(e);
}
}
public ConfigItem(final String label, final int contentIndex,
final List<E> identifiers) {
this(label, true, identifiers);
setContentIndex(contentIndex);
}
@Override
public final String getContent() {
return content;
}
public final void setContent(final String content)
throws ConfigurationException {
if (content == null) throw new NullPointerException("content");
if (!freeAssign && !identifiers.contains(content))
throw new ConfigurationException("Invalid constant "
+ "for '%s': '%s' - must be one of '%s'", getLabel(),
content, Arrays.toString(identifiers.toArray()));
checkValidString(content, false);
this.content = content;
if (cb != null) cb.setSelectedItem(content);
}
public final void setContentIndex(final int content) {
if (content < 0 || content >= identifiers.size())
throw new IndexOutOfBoundsException(String.format(
"New content %d for '%s' must be between 0 "
+ "and %d for '%s'", content, getLabel(),
identifiers.size() - 1,
Arrays.toString(identifiers.toArray())));
this.content = identifiers.get(content);
if (cb != null) cb.setSelectedIndex(content);
}
public final String getContentGUI() {
return cb == null ? content : (String) cb.getSelectedItem();
}
public final void setContentGUI(final String content) {
internalMod = true;
try {
if (cb != null) cb.setSelectedItem(content);
} finally {
internalMod = false;
}
}
public final void setContentIndexGUI(final int content) {
internalMod = true;
try {
if (cb != null) cb.setSelectedIndex(content);
} finally {
internalMod = false;
}
}
public final List<String> getIdentifiers() {
return Collections.unmodifiableList(identifiers);
}
@Override
public final String asString() {
return content;
}
@Override
public final void setFromString(final String string)
throws ConfigurationException {
setContent(string);
}
@Override
final List<String> asStrings() {
throw new UnsupportedOperationException();
}
@Override
final void setFromStrings(final List<String> strings) {
throw new UnsupportedOperationException();
}
@Override
public final String getIdentifier() {
return null;
}
@Override
final boolean isSingleLined() {
return true;
}
@Override
public final boolean insertGUIComponents(final Layouter lay) {
cb = new JComboBox(identifiers.toArray());
cb.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (!isInternalMod())
invokeChangingContent(getCb().getSelectedItem());
}
});
cb.setEditable(freeAssign);
cb.setSelectedItem(content);
lay.add(cb, true);
invokeChangingContent(cb.getSelectedItem());
return false;
}
@Override
public final void setFromGUIComponents() {
try {
setContent(cb.getSelectedItem().toString());
} catch (final ConfigurationException e) {
Log.error(e, "Cannot set value '%s'", getLabel());
}
}
@Override
public final void setGUIEnabled(final boolean enabled) {
if (cb != null) cb.setEnabled(enabled);
}
protected final JComboBox getCb() {
return cb;
}
protected final boolean isInternalMod() {
return internalMod;
}
}