
org.bidib.wizard.mvc.loco.view.ScriptPanel Maven / Gradle / Ivy
package org.bidib.wizard.mvc.loco.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.lang.StringUtils;
import org.bidib.wizard.dialog.FileDialog;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.script.ScriptCommand;
import org.bidib.wizard.script.ScriptCommandFactory;
import org.bidib.wizard.script.ScriptEngineListener;
import org.bidib.wizard.script.engine.ScriptEngine;
import org.bidib.wizard.script.engine.ScriptEngine.ScriptStatus;
import org.bidib.wizard.script.loco.StopEmergencyCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.value.ValueHolder;
import com.jgoodies.binding.value.ValueModel;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
public class ScriptPanel implements LocoViewListener, ScriptEngineListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ScriptPanel.class);
// description, suffix for script files
private static String scriptDescription;
private static final String SCRIPT_EXTENSION = "dcct";
private static FileFilter scriptFilter;
private ValueModel selectedScriptModel = new ValueHolder();
private ValueModel currentCommandModel = new ValueHolder();
private JButton startScript;
private JButton stopScript;
private LocoViewScripting scripting;
private ScriptEngine scriptEngine;
private ValueModel checkRepeatingModel = new ValueHolder();
private AtomicBoolean scriptRepeating = new AtomicBoolean(false);
private JPanel contentPanel;
public ScriptPanel(LocoViewScripting scripting) {
this.scripting = scripting;
scriptDescription = Resources.getString(ScriptPanel.class, "scriptDescription");
scriptFilter = new FileNameExtensionFilter(scriptDescription, SCRIPT_EXTENSION);
}
public JPanel createPanel() {
// create the script engine
scriptEngine = new ScriptEngine(scripting, new HashMap());
scriptEngine.addScriptEngineListener(this);
checkRepeatingModel.setValue(scriptRepeating.get());
DefaultFormBuilder formBuilder = new DefaultFormBuilder(new FormLayout("60dlu, 3dlu, 60dlu, 3dlu, 0dlu:grow"));
JButton selectScript = new JButton(Resources.getString(ScriptPanel.class, "selectScript"));
selectScript.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// select the script file
FileDialog dialog = new FileDialog(
contentPanel, FileDialog.OPEN, "*." + SCRIPT_EXTENSION, scriptFilter) {
@Override
public void approve(String fileName) {
LOGGER.info("Load script: {}", fileName);
try {
File file = new File(fileName);
if (file.exists()) {
LOGGER.info("The script file exists: {}", file);
selectedScriptModel.setValue(file.getName());
prepareScript(fileName);
startScript.setEnabled(true);
}
else {
selectedScriptModel.setValue("no script selected");
startScript.setEnabled(false);
}
}
catch (IOException ex) {
LOGGER.info("Load and process script file failed.", ex);
startScript.setEnabled(false);
}
finally {
}
}
};
dialog.showDialog();
}
});
formBuilder.append(selectScript);
JLabel scriptLabel = BasicComponentFactory.createLabel(selectedScriptModel);
formBuilder.append(scriptLabel, 3);
JCheckBox repeatingCheck =
BasicComponentFactory.createCheckBox(checkRepeatingModel,
Resources.getString(ScriptPanel.class, "repeating"));
formBuilder.nextLine();
formBuilder.append(repeatingCheck, 3);
formBuilder.nextLine();
startScript = new JButton(Resources.getString(ScriptPanel.class, "startScript"));
startScript.setEnabled(false);
startScript.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
scriptEngine.startScript();
}
});
formBuilder.append(startScript);
stopScript = new JButton(Resources.getString(ScriptPanel.class, "stopScript"));
stopScript.setEnabled(false);
stopScript.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stopScript();
}
});
formBuilder.append(stopScript);
JLabel currentCommandLabel = BasicComponentFactory.createLabel(currentCommandModel);
formBuilder.append(currentCommandLabel);
checkRepeatingModel.addValueChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.info("Repeating has changed: {}", checkRepeatingModel.getValue());
Boolean repeating = (Boolean) checkRepeatingModel.getValue();
scriptRepeating.set(repeating);
scriptEngine.setScriptRepeating(repeating);
}
});
contentPanel = formBuilder.build();
return contentPanel;
}
public void currentCommandChanged(final ScriptCommand command) {
if (SwingUtilities.isEventDispatchThread()) {
currentCommandModel.setValue((command != null ? command.toString() : null));
}
else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
currentCommandModel.setValue((command != null ? command.toString() : null));
}
});
}
catch (InvocationTargetException | InterruptedException e) {
LOGGER.warn("Update current command failed.", e);
}
}
}
private void stopScript() {
LOGGER.info("Stop the script.");
scriptEngine.stopScript();
}
@Override
public void scriptStatusChanged(final ScriptStatus scriptStatus) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
switch (scriptStatus) {
case RUNNING:
startScript.setEnabled(false);
stopScript.setEnabled(true);
break;
case STOPPED:
case FINISHED:
startScript.setEnabled(true);
stopScript.setEnabled(false);
break;
}
currentCommandChanged(null);
}
});
}
@Override
public void stop() {
LOGGER.info("Stop was signalled.");
}
@Override
public void emergencyStop() {
LOGGER.info("EmergencyStop was signalled.");
if (!StopEmergencyCommand.KEY.equals(currentCommandModel.getValue())) {
LOGGER.info("EmergencyStop was triggered. Stop the script.");
stopScript();
}
}
private final static Charset ENCODING = StandardCharsets.UTF_8;
private void prepareScript(String fileName) throws IOException {
Path fFilePath = Paths.get(fileName);
ScriptCommandFactory factory = new ScriptCommandFactory();
List> scriptCommands = new LinkedList>();
try (Scanner scanner = new Scanner(fFilePath, ENCODING.name())) {
while (scanner.hasNextLine()) {
processLine(scanner.nextLine().trim(), factory, scriptCommands);
}
}
LOGGER.info("Prepared list of commands: {}", scriptCommands);
scriptEngine.setScriptCommands(scriptCommands);
}
private void processLine(
String line, ScriptCommandFactory factory,
List> scriptCommands) {
LOGGER.info("Process line: {}", line);
if (line.startsWith("#") || StringUtils.isBlank(line)) {
LOGGER.info("Skip comment or empty line.");
}
else {
LOGGER.info("Current line: {}", line);
ScriptCommand command = factory.parse(line);
if (command != null) {
scriptCommands.add(command);
}
}
}
public void close() {
if (scriptEngine != null) {
LOGGER.info("Release the scriptEngine.");
scriptEngine.removeScriptEngineListener(this);
scriptEngine = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy