// 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.itfc.gui.dse;
import java.io.IOException;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import pleocmd.Log;
import pleocmd.cfg.ConfigDataMap;
import pleocmd.exc.ConfigurationException;
import pleocmd.exc.FormatException;
import pleocmd.itfc.gui.Layouter;
import pleocmd.pipe.data.Data;
public final class DataSequenceTriggerPanel extends JPanel {
private static final long serialVersionUID = -8090213458513567801L;
private final ConfigDataMap map;
private final ConfigDataMap mapOrg;
private final JSplitPane splitPane;
private final JList triggerList;
private final DataSequenceEditorListModel triggerModel;
private final JButton btnAddTrigger;
private final JButton btnRenameTrigger;
private final JButton btnRemoveTrigger;
private final DataSequenceEditorPanel dsePanel;
private String trigger;
public DataSequenceTriggerPanel(final ConfigDataMap cfgMap) {
mapOrg = cfgMap;
map = new ConfigDataMap(mapOrg.getLabel());
map.assignFrom(mapOrg);
// Add components
final Layouter lay = new Layouter(this);
final JPanel panel = new JPanel();
final Layouter layInner = new Layouter(panel);
triggerModel = new DataSequenceEditorListModel();
triggerList = new JList(triggerModel);
triggerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
layInner.addWholeLine(new JScrollPane(triggerList), true);
triggerList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent e) {
triggerIndexChanged();
}
});
layInner.add(new JLabel("Trigger:"), false);
btnAddTrigger = layInner.addButton("Add", "list-add",
"Add a new trigger to the list", new Runnable() {
@Override
public void run() {
addNewTrigger();
}
});
btnRenameTrigger = layInner.addButton("Rename", "edit-rename",
"Change the name of the select trigger", new Runnable() {
@Override
public void run() {
renameSelectedTrigger();
}
});
layInner.addSpacer();
btnRemoveTrigger = layInner.addButton("Remove", "list-remove",
"Remove the selected trigger from the list", new Runnable() {
@Override
public void run() {
removeSelectedTrigger();
}
});
dsePanel = new DataSequenceEditorPanel() {
private static final long serialVersionUID = -4279793671317418153L;
@Override
protected void stateChanged() {
// nothing to do here
}
};
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, panel,
dsePanel);
splitPane.setResizeWeight(0.25);
lay.addWholeLine(splitPane, true);
updateTriggerModel();
updateState();
}
public void saveChanges() {
writeTextPaneToMap();
mapOrg.setInternalMod(true);
try {
mapOrg.assignFrom(map);
} finally {
mapOrg.setInternalMod(false);
}
}
protected void triggerIndexChanged() {
final Object newTrigger = triggerList.getSelectedValue();
if (trigger == newTrigger) return;
writeTextPaneToMap();
trigger = (String) newTrigger;
updateTextPaneFromMap();
updateState();
}
private void writeTextPaneToMap() {
Log.detail("Writing TextPane to map with '%s'", trigger);
try {
final List<Data> list = dsePanel.writeTextPaneToList();
if (trigger == null) {
if (!list.isEmpty())
throw new IOException("No name selected in JList");
} else {
map.setContent(trigger, list);
modified();
}
} catch (final ConfigurationException e) {
Log.error(e);
} catch (final IOException e) {
Log.error(e);
} catch (final FormatException e) {
Log.error(e);
}
}
private void updateTextPaneFromMap() {
Log.detail("Updating TextPane from map with '%s'", trigger);
dsePanel.updateTextPaneFromList(trigger == null ? null : map
.getContent(trigger));
}
protected void updateTriggerModel() {
final Object lastSelected = trigger;
triggerModel.set(map.getAllKeysSorted());
Log.detail("Updating trigger model for map '%s' - last selected '%s'",
map, lastSelected);
triggerList.setSelectedValue(lastSelected, true);
}
protected void addNewTrigger() {
final String name = JOptionPane.showInputDialog(this,
"Name of the new trigger", "Add new trigger",
JOptionPane.PLAIN_MESSAGE);
if (name != null) {
try {
map.createContent(name);
Log.detail("Added new trigger '%s' to '%s'", name, map);
modified();
} catch (final ConfigurationException e) {
Log.error(e);
}
updateTriggerModel();
triggerList.setSelectedValue(name, true);
}
}
protected void renameSelectedTrigger() {
if (trigger != null) {
final String name = (String) JOptionPane.showInputDialog(this,
"New Name of the trigger", "Rename trigger",
JOptionPane.PLAIN_MESSAGE, null, null, trigger);
if (name != null) {
try {
map.renameContent(trigger, name);
Log.detail("Renamed trigger '%s' to '%s' in '%s'", trigger,
name, map);
modified();
} catch (final ConfigurationException e) {
Log.error(e);
}
trigger = name;
updateTriggerModel();
triggerList.setSelectedValue(name, true);
updateState();
}
}
}
protected void removeSelectedTrigger() {
if (trigger != null) {
map.removeContent(trigger);
Log.detail("Removed trigger '%s' from '%s'", trigger, map);
dsePanel.clear();
trigger = null;
updateTriggerModel();
updateState();
modified();
}
}
public void modified() {
mapOrg.dstpModified(map);
}
protected void updateState() {
btnAddTrigger.setEnabled(true);
btnRenameTrigger.setEnabled(trigger != null);
btnRemoveTrigger.setEnabled(trigger != null);
dsePanel.setEnabled(trigger != null);
dsePanel.updateState();
}
public void externalChanged(final ConfigDataMap other) {
Log.detail("Replacing map '%s' with '%s' due to external change", map,
other);
map.assignFrom(other);
updateTriggerModel();
updateState();
modified();
}
public ConfigDataMap getMap() {
return map;
}
}