// 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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import pleocmd.Log;
import pleocmd.exc.ConfigurationException;
import pleocmd.exc.InternalException;
import pleocmd.itfc.gui.Layouter;
public abstract class ConfigCollection<E> extends ConfigValue {
public enum Type {
Set, List
}
private final Type type;
private final Collection<E> content;
private JTextArea ta;
private boolean internalMod;
public ConfigCollection(final String label, final Type type) {
super(label);
this.type = type;
switch (type) {
case List:
content = new ArrayList<E>();
break;
case Set:
content = new HashSet<E>();
break;
default:
throw new InternalException(type);
}
}
public ConfigCollection(final String label, final Type type,
final Collection<E> content) {
this(label, type);
try {
setContent(content);
} catch (final ConfigurationException e) {
throw new IllegalArgumentException(
"Cannot initialize default content", e);
}
}
public final Type getType() {
return type;
}
@Override
public final Collection<E> getContent() {
return Collections.unmodifiableCollection(content);
}
public final void setContent(final Collection<? extends E> content)
throws ConfigurationException {
clearContent();
addContent(content);
}
public final <F extends E> void addContent(final F item)
throws ConfigurationException {
checkValidString(item.toString(), false);
content.add(item);
if (ta != null) ta.setText(asString());
}
public final void addContent(final Collection<? extends E> contentToAdd)
throws ConfigurationException {
for (final Object o : contentToAdd)
checkValidString(o.toString(), false);
content.addAll(contentToAdd);
if (ta != null) ta.setText(asString());
}
public final <F extends E> boolean removeContent(final F item) {
if (item == null) throw new NullPointerException();
final boolean res = content.remove(item);
if (ta != null) ta.setText(asString());
return res;
}
public final <F extends E> boolean contains(final F item) {
if (item == null) throw new NullPointerException();
return content.contains(item);
}
public final void clearContent() {
content.clear();
if (ta != null) ta.setText(asString());
}
public final Collection<E> getContentGUI() {
if (ta == null) return getContent();
final List<E> list = new ArrayList<E>();
final StringTokenizer st = new StringTokenizer(ta.getText(), "\n");
try {
while (st.hasMoreTokens())
list.add(createItem(st.nextToken()));
} catch (final ConfigurationException e) {
return null;
}
return list;
}
public final void setContentGUI(final Collection<? extends E> content) {
internalMod = true;
try {
if (ta != null) ta.setText(contentAsStringNL(content));
} finally {
internalMod = false;
}
}
public final void clearContentGUI() {
internalMod = true;
try {
if (ta != null) ta.setText("");
} finally {
internalMod = false;
}
}
@Override
public final String asString() {
return content.toString();
}
private final String contentAsStringNL(final Collection<? extends E> cont) {
final StringBuffer sb = new StringBuffer();
for (final E item : cont) {
sb.append(item.toString());
sb.append('\n');
}
if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
@Override
public final void setFromString(final String string)
throws ConfigurationException {
final List<E> list = new ArrayList<E>();
final StringTokenizer st = new StringTokenizer(string, "\n");
while (st.hasMoreTokens())
list.add(createItem(st.nextToken()));
setContent(list);
}
protected abstract E createItem(String itemAsString)
throws ConfigurationException;
@Override
final List<String> asStrings() {
final List<String> list = new ArrayList<String>(content.size());
for (final E item : content)
list.add(item.toString());
return list;
}
@Override
final void setFromStrings(final List<String> strings)
throws ConfigurationException {
final List<E> list = new ArrayList<E>(strings.size());
for (final String str : strings)
list.add(createItem(str));
setContent(list);
}
@Override
public final String getIdentifier() {
switch (type) {
case List:
return "list";
case Set:
return "set";
default:
throw new InternalException(type);
}
}
@Override
final boolean isSingleLined() {
return false;
}
@Override
public final boolean insertGUIComponents(final Layouter lay) {
ta = new JTextArea(contentAsStringNL(content), 5, 20);
ta.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(final UndoableEditEvent e) {
if (!isInternalMod()) invokeChangingContent(getTa().getText());
}
});
lay.addWholeLine(new JScrollPane(ta), true);
invokeChangingContent(ta.getText());
return true;
}
@Override
public final void setFromGUIComponents() {
try {
setFromString(ta.getText());
} catch (final ConfigurationException e) {
Log.error(e, "Cannot set value '%s'", getLabel());
}
}
@Override
public final void setGUIEnabled(final boolean enabled) {
if (ta != null) ta.setEnabled(enabled);
}
protected final JTextArea getTa() {
return ta;
}
protected final boolean isInternalMod() {
return internalMod;
}
}