All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.mvc.loco.view.ScriptPanel Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
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