001package jmri.jmrit.operations.trains.tools;
002
003import java.awt.GridBagLayout;
004import java.io.File;
005import java.util.List;
006
007import javax.swing.*;
008
009import jmri.InstanceManager;
010import jmri.jmrit.operations.OperationsFrame;
011import jmri.jmrit.operations.OperationsXml;
012import jmri.jmrit.operations.setup.Setup;
013import jmri.jmrit.operations.trains.TrainManager;
014import jmri.script.JmriScriptEngineManager;
015import jmri.script.swing.ScriptFileChooser;
016import jmri.util.FileUtil;
017import jmri.util.swing.JmriJOptionPane;
018
019/**
020 * Frame for user edit of startup and shutdown operation scripts.
021 *
022 * @author Bob Jacobsen Copyright (C) 2004
023 * @author Dan Boudreau Copyright (C) 2011
024 */
025public class TrainsScriptFrame extends OperationsFrame {
026
027    TrainManager trainManager = InstanceManager.getDefault(TrainManager.class);
028
029    // script panels
030    JPanel pStartUpScript = new JPanel();
031    JPanel pShutDownScript = new JPanel();
032    JScrollPane startUpScriptPane;
033    JScrollPane shutDownScriptPane;
034
035    // labels
036    // major buttons
037    JButton addStartUpScriptButton = new JButton(Bundle.getMessage("AddScript"));
038    JButton addShutDownScriptButton = new JButton(Bundle.getMessage("AddScript"));
039    JButton runStartUpScriptButton = new JButton(Bundle.getMessage("RunScripts"));
040    JButton runShutDownScriptButton = new JButton(Bundle.getMessage("RunScripts"));
041    JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
042
043    public TrainsScriptFrame() {
044        super();
045    }
046
047    @Override
048    public void initComponents() {
049        // Set up script options in a Scroll Pane..
050        startUpScriptPane = new JScrollPane(pStartUpScript);
051        startUpScriptPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
052        startUpScriptPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ScriptsStartUp")));
053
054        shutDownScriptPane = new JScrollPane(pShutDownScript);
055        shutDownScriptPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
056        shutDownScriptPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ScriptsShutDown")));
057
058        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
059
060        // Layout the panel by rows
061        // row 1
062        updateStartUpScriptPanel();
063
064        // row 3
065        updateShutDownScriptPanel();
066
067        // row 4 buttons
068        JPanel pB = new JPanel();
069        pB.setLayout(new GridBagLayout());
070        addItem(pB, saveButton, 3, 0);
071
072        getContentPane().add(startUpScriptPane);
073        getContentPane().add(shutDownScriptPane);
074        getContentPane().add(pB);
075
076        // setup buttons
077        addButtonAction(addStartUpScriptButton);
078        addButtonAction(addShutDownScriptButton);
079        addButtonAction(runStartUpScriptButton);
080        addButtonAction(runShutDownScriptButton);
081        addButtonAction(saveButton);
082
083        enableButtons(true);
084
085        addHelpMenu("package.jmri.jmrit.operations.Operations_TrainScripts", true); // NOI18N
086        packFrame();
087        initMinimumSize();
088    }
089
090    private void updateStartUpScriptPanel() {
091        pStartUpScript.removeAll();
092        pStartUpScript.setLayout(new GridBagLayout());
093        addItem(pStartUpScript, addStartUpScriptButton, 0, 0);
094
095        // load any existing startup scripts
096        List<String> scripts = trainManager.getStartUpScripts();
097        if (scripts.size() > 0) {
098            addItem(pStartUpScript, runStartUpScriptButton, 1, 0);
099        }
100        for (int i = 0; i < scripts.size(); i++) {
101            JButton removeStartUpScripts = new JButton(Bundle.getMessage("RemoveScript"));
102            removeStartUpScripts.setName(scripts.get(i));
103            removeStartUpScripts.addActionListener(new java.awt.event.ActionListener() {
104                @Override
105                public void actionPerformed(java.awt.event.ActionEvent e) {
106                    buttonActionRemoveStartUpScript(e);
107                }
108            });
109            addButtonAction(removeStartUpScripts);
110            JLabel pathname = new JLabel(scripts.get(i));
111            addItem(pStartUpScript, removeStartUpScripts, 0, i + 1);
112            addItem(pStartUpScript, pathname, 1, i + 1);
113        }
114    }
115
116    private void updateShutDownScriptPanel() {
117        pShutDownScript.removeAll();
118        pShutDownScript.setLayout(new GridBagLayout());
119        addItem(pShutDownScript, addShutDownScriptButton, 0, 0);
120
121        // load any existing shutdown scripts
122        List<String> scripts = trainManager.getShutDownScripts();
123        if (scripts.size() > 0) {
124            addItem(pShutDownScript, runShutDownScriptButton, 1, 0);
125        }
126        for (int i = 0; i < scripts.size(); i++) {
127            JButton removeShutDownScripts = new JButton(Bundle.getMessage("RemoveScript"));
128            removeShutDownScripts.setName(scripts.get(i));
129            removeShutDownScripts.addActionListener(new java.awt.event.ActionListener() {
130                @Override
131                public void actionPerformed(java.awt.event.ActionEvent e) {
132                    buttonActionRemoveShutDownScript(e);
133                }
134            });
135            JLabel pathname = new JLabel(scripts.get(i));
136            addItem(pShutDownScript, removeShutDownScripts, 0, i + 1);
137            addItem(pShutDownScript, pathname, 1, i + 1);
138        }
139    }
140
141    // Save train, add scripts buttons
142    @Override
143    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
144        if (ae.getSource() == addStartUpScriptButton) {
145            log.debug("train add move script button activated");
146            File f = selectFile();
147            if (f != null) {
148                trainManager.addStartUpScript(FileUtil.getPortableFilename(f));
149                updateStartUpScriptPanel();
150                packFrame();
151            }
152        }
153        if (ae.getSource() == addShutDownScriptButton) {
154            log.debug("train add termination script button activated");
155            File f = selectFile();
156            if (f != null) {
157                trainManager.addShutDownScript(FileUtil.getPortableFilename(f));
158                updateShutDownScriptPanel();
159                packFrame();
160            }
161        }
162        if (ae.getSource() == runStartUpScriptButton) {
163            runScripts(trainManager.getStartUpScripts());
164        }
165        if (ae.getSource() == runShutDownScriptButton) {
166            runScripts(trainManager.getShutDownScripts());
167        }
168        if (ae.getSource() == saveButton) {
169            log.debug("Save button activated");
170            OperationsXml.save();
171            if (Setup.isCloseWindowOnSaveEnabled()) {
172                dispose();
173            }
174        }
175    }
176
177    public void buttonActionRemoveStartUpScript(java.awt.event.ActionEvent ae) {
178        JButton rbutton = (JButton) ae.getSource();
179        log.debug("remove move script button activated {}", rbutton.getName());
180        trainManager.deleteStartUpScript(rbutton.getName());
181        updateStartUpScriptPanel();
182        packFrame();
183    }
184
185    public void buttonActionRemoveShutDownScript(java.awt.event.ActionEvent ae) {
186        JButton rbutton = (JButton) ae.getSource();
187        log.debug("remove termination script button activated {}", rbutton.getName());
188        trainManager.deleteShutDownScript(rbutton.getName());
189        updateShutDownScriptPanel();
190        packFrame();
191    }
192
193    /**
194     * We always use the same file chooser in this class, so that the user's
195     * last-accessed directory remains available.
196     */
197    ScriptFileChooser fc;
198
199    private File selectFile() {
200        if (fc == null) {
201            fc = new ScriptFileChooser(FileUtil.getUserFilesPath());
202            fc.setDialogTitle(Bundle.getMessage("FindDesiredScriptFile"));
203        }
204        // when reusing the chooser, make sure new files are included
205        fc.rescanCurrentDirectory();
206        int retVal = fc.showOpenDialog(null);
207        // handle selection or cancel
208        if (retVal == JFileChooser.APPROVE_OPTION) {
209            return fc.getSelectedFile();
210        }
211        return null;
212    }
213
214    private void enableButtons(boolean enabled) {
215        addStartUpScriptButton.setEnabled(enabled);
216        addShutDownScriptButton.setEnabled(enabled);
217        saveButton.setEnabled(enabled);
218    }
219
220    private void runScripts(List<String> scripts) {
221        for (String script : scripts) {
222            String scriptPathname = jmri.util.FileUtil.getExternalFilename(script);
223            File file = new File(scriptPathname);
224            if (file.exists()) {
225                JmriScriptEngineManager.getDefault().runScript(file);
226            } else {
227                JmriJOptionPane.showMessageDialog(this, script, Bundle.getMessage("ScriptFileNotFound"),
228                        JmriJOptionPane.ERROR_MESSAGE);
229            }
230
231        }
232    }
233
234    private void packFrame() {
235        setPreferredSize(null);
236        pack();
237    }
238
239    @Override
240    public void dispose() {
241        super.dispose();
242    }
243
244    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainsScriptFrame.class.getName());
245}