001package jmri.jmrit.dispatcher;
002
003import java.awt.Container;
004import java.awt.FlowLayout;
005import java.awt.event.ActionEvent;
006import java.awt.event.ActionListener;
007import java.awt.event.ItemEvent;
008import java.awt.event.ItemListener;
009import java.util.ArrayList;
010import java.util.HashSet;
011import java.util.List;
012import java.util.Set;
013
014import javax.swing.BorderFactory;
015import javax.swing.BoxLayout;
016import javax.swing.ButtonGroup;
017import javax.swing.JButton;
018import javax.swing.JCheckBox;
019import javax.swing.JComboBox;
020import javax.swing.JLabel;
021import javax.swing.JPanel;
022import javax.swing.JRadioButton;
023import javax.swing.JScrollPane;
024import javax.swing.JSeparator;
025import javax.swing.JSpinner;
026import javax.swing.JTextField;
027import javax.swing.SpinnerNumberModel;
028
029import jmri.Block;
030import jmri.InstanceManager;
031import jmri.Sensor;
032import jmri.Transit;
033import jmri.TransitManager;
034import jmri.jmrit.dispatcher.ActiveTrain.TrainDetection;
035import jmri.jmrit.dispatcher.DispatcherFrame.TrainsFrom;
036import jmri.jmrit.operations.trains.Train;
037import jmri.jmrit.operations.trains.TrainManager;
038import jmri.jmrit.roster.RosterEntry;
039import jmri.jmrit.roster.swing.RosterEntryComboBox;
040import jmri.swing.NamedBeanComboBox;
041import jmri.util.JmriJFrame;
042import jmri.util.swing.JComboBoxUtil;
043import jmri.util.swing.JmriJOptionPane;
044
045/**
046 * Displays the Activate New Train dialog and processes information entered
047 * there.
048 * <p>
049 * This module works with Dispatcher, which initiates the display of the dialog.
050 * Dispatcher also creates the ActiveTrain.
051 * <p>
052 * This file is part of JMRI.
053 * <p>
054 * JMRI is open source software; you can redistribute it and/or modify it under
055 * the terms of version 2 of the GNU General Public License as published by the
056 * Free Software Foundation. See the "COPYING" file for a copy of this license.
057 * <p>
058 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
059 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
060 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
061 *
062 * @author Dave Duchamp Copyright (C) 2009
063 */
064public class ActivateTrainFrame extends JmriJFrame {
065
066    public ActivateTrainFrame(DispatcherFrame d) {
067        super(true,true);
068        _dispatcher = d;
069        _tiFile = new TrainInfoFile();
070    }
071
072    // operational instance variables
073    private DispatcherFrame _dispatcher = null;
074    private TrainInfoFile _tiFile = null;
075    private final TransitManager _TransitManager = InstanceManager.getDefault(jmri.TransitManager.class);
076    private String _trainInfoName = "";
077
078    // initiate train window variables
079    private Transit selectedTransit = null;
080    //private String selectedTrain = "";
081    private JmriJFrame initiateFrame = null;
082    private Container initiatePane = null;
083    private final jmri.swing.NamedBeanComboBox<Transit> transitSelectBox = new jmri.swing.NamedBeanComboBox<>(_TransitManager);
084    private final JLabel trainBoxLabel = new JLabel("     " + Bundle.getMessage("TrainBoxLabel") + ":");
085    private final JComboBox<Object> trainSelectBox = new JComboBox<>();
086    // private final List<RosterEntry> trainBoxList = new ArrayList<>();
087    private RosterEntryComboBox rosterComboBox = null;
088    private final JLabel trainFieldLabel = new JLabel(Bundle.getMessage("TrainBoxLabel") + ":");
089    private final JTextField trainNameField = new JTextField(10);
090    private final JLabel dccAddressFieldLabel = new JLabel("     " + Bundle.getMessage("DccAddressFieldLabel") + ":");
091    private final JSpinner dccAddressSpinner = new JSpinner(new SpinnerNumberModel(3, 1, 9999, 1));
092    private final JCheckBox inTransitBox = new JCheckBox(Bundle.getMessage("TrainInTransit"));
093    private final JComboBox<String> startingBlockBox = new JComboBox<>();
094    private List<Block> startingBlockBoxList = new ArrayList<>();
095    private List<Integer> startingBlockSeqList = new ArrayList<>();
096    private final JComboBox<String> destinationBlockBox = new JComboBox<>();
097    private List<Block> destinationBlockBoxList = new ArrayList<>();
098    private List<Integer> destinationBlockSeqList = new ArrayList<>();
099    private JButton addNewTrainButton = null;
100    private JButton loadButton = null;
101    private JButton saveButton = null;
102    private JButton deleteButton = null;
103    private final JCheckBox autoRunBox = new JCheckBox(Bundle.getMessage("AutoRun"));
104    private final JCheckBox loadAtStartupBox = new JCheckBox(Bundle.getMessage("LoadAtStartup"));
105
106    private final JRadioButton radioTrainsFromRoster = new JRadioButton(Bundle.getMessage("TrainsFromRoster"));
107    private final JRadioButton radioTrainsFromOps = new JRadioButton(Bundle.getMessage("TrainsFromTrains"));
108    private final JRadioButton radioTrainsFromUser = new JRadioButton(Bundle.getMessage("TrainsFromUser"));
109    private final JRadioButton radioTrainsFromSetLater = new JRadioButton(Bundle.getMessage("TrainsFromSetLater"));
110    private final ButtonGroup trainsFromButtonGroup = new ButtonGroup();
111
112    private final JRadioButton allocateBySafeRadioButton = new JRadioButton(Bundle.getMessage("ToSafeSections"));
113    private final JRadioButton allocateAllTheWayRadioButton = new JRadioButton(Bundle.getMessage("AsFarAsPos"));
114    private final JRadioButton allocateNumberOfBlocks = new JRadioButton(Bundle.getMessage("NumberOfBlocks") + ":");
115    private final ButtonGroup allocateMethodButtonGroup = new ButtonGroup();
116    private final JSpinner allocateCustomSpinner = new JSpinner(new SpinnerNumberModel(3, 1, 100, 1));
117    private final JCheckBox terminateWhenDoneBox = new JCheckBox(Bundle.getMessage("TerminateWhenDone"));
118    private final JPanel terminateWhenDoneDetails = new JPanel();
119    private final JComboBox<String> nextTrain = new JComboBox<>();
120    private final JLabel nextTrainLabel = new JLabel(Bundle.getMessage("TerminateWhenDoneNextTrain"));
121    private final JSpinner prioritySpinner = new JSpinner(new SpinnerNumberModel(5, 0, 100, 1));
122    private final JCheckBox resetWhenDoneBox = new JCheckBox(Bundle.getMessage("ResetWhenDone"));
123    private final JCheckBox reverseAtEndBox = new JCheckBox(Bundle.getMessage("ReverseAtEnd"));
124
125    int delayedStartInt[] = new int[]{ActiveTrain.NODELAY, ActiveTrain.TIMEDDELAY, ActiveTrain.SENSORDELAY};
126    String delayedStartString[] = new String[]{Bundle.getMessage("DelayedStartNone"), Bundle.getMessage("DelayedStartTimed"), Bundle.getMessage("DelayedStartSensor")};
127
128    private final JComboBox<String> reverseDelayedRestartType = new JComboBox<>(delayedStartString);
129    private final JLabel delayReverseReStartLabel = new JLabel(Bundle.getMessage("DelayRestart"));
130    private final JLabel delayReverseReStartSensorLabel = new JLabel(Bundle.getMessage("RestartSensor"));
131    private final JCheckBox delayReverseResetSensorBox = new JCheckBox(Bundle.getMessage("ResetRestartSensor"));
132    private final NamedBeanComboBox<Sensor> delayReverseReStartSensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance());
133    private final JSpinner delayReverseMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
134    private final JLabel delayReverseMinLabel = new JLabel(Bundle.getMessage("RestartTimed"));
135
136    private final JCheckBox resetStartSensorBox = new JCheckBox(Bundle.getMessage("ResetStartSensor"));
137    private final JComboBox<String> delayedStartBox = new JComboBox<>(delayedStartString);
138    private final JLabel delayedReStartLabel = new JLabel(Bundle.getMessage("DelayRestart"));
139    private final JLabel delayReStartSensorLabel = new JLabel(Bundle.getMessage("RestartSensor"));
140    private final JCheckBox resetRestartSensorBox = new JCheckBox(Bundle.getMessage("ResetRestartSensor"));
141    private final JComboBox<String> delayedReStartBox = new JComboBox<>(delayedStartString);
142    private final NamedBeanComboBox<Sensor> delaySensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance());
143    private final NamedBeanComboBox<Sensor> delayReStartSensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance());
144
145    private final JSpinner departureHrSpinner = new JSpinner(new SpinnerNumberModel(8, 0, 23, 1));
146    private final JSpinner departureMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 59, 1));
147    private final JLabel departureTimeLabel = new JLabel(Bundle.getMessage("DepartureTime"));
148    private final JLabel departureSepLabel = new JLabel(":");
149
150    private final JSpinner delayMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
151    private final JLabel delayMinLabel = new JLabel(Bundle.getMessage("RestartTimed"));
152
153    private final JComboBox<String> trainTypeBox = new JComboBox<>();
154    // Note: See also items related to automatically running trains near the end of this module
155
156    boolean transitsFromSpecificBlock = false;
157
158    private TrainInfo trainInfo;
159
160    /**
161     * Open up a new train window for a given roster entry located in a specific
162     * block.
163     *
164     * @param e  the action event triggering the new window
165     * @param re the roster entry to open the new window for
166     * @param b  the block where the train is located
167     */
168    public void initiateTrain(ActionEvent e, RosterEntry re, Block b) {
169        initiateTrain(e);
170        if (trainInfo.getTrainsFrom() == TrainsFrom.TRAINSFROMROSTER && re != null) {
171            setRosterComboBox(rosterComboBox, re.getId());
172            //Add in some bits of code as some point to filter down the transits that can be used.
173        }
174        if (b != null && selectedTransit != null) {
175            List<Transit> transitList = _TransitManager.getListUsingBlock(b);
176            List<Transit> transitEntryList = _TransitManager.getListEntryBlock(b);
177            for (Transit t : transitEntryList) {
178                if (!transitList.contains(t)) {
179                    transitList.add(t);
180                }
181            }
182            transitsFromSpecificBlock = true;
183            initializeFreeTransitsCombo(transitList);
184            List<Block> tmpBlkList = new ArrayList<>();
185            if (selectedTransit.getEntryBlocksList().contains(b)) {
186                tmpBlkList = selectedTransit.getEntryBlocksList();
187                inTransitBox.setSelected(false);
188            } else if (selectedTransit.containsBlock(b)) {
189                tmpBlkList = selectedTransit.getInternalBlocksList();
190                inTransitBox.setSelected(true);
191            }
192            List<Integer> tmpSeqList = selectedTransit.getBlockSeqList();
193            for (int i = 0; i < tmpBlkList.size(); i++) {
194                if (tmpBlkList.get(i) == b) {
195                    setComboBox(startingBlockBox, getBlockName(b) + "-" + tmpSeqList.get(i));
196                    break;
197                }
198            }
199        }
200    }
201
202    /**
203     * Displays a window that allows a new ActiveTrain to be activated.
204     * <p>
205     * Called by Dispatcher in response to the dispatcher clicking the New Train
206     * button.
207     *
208     * @param e the action event triggering the window display
209     */
210    protected void initiateTrain(ActionEvent e) {
211        // set Dispatcher defaults
212        // create window if needed
213        trainInfo = new TrainInfo();
214        trainInfo.setTrainsFrom(_dispatcher.getTrainsFrom());
215
216        if (initiateFrame == null) {
217            initiateFrame = this;
218            initiateFrame.setTitle(Bundle.getMessage("AddTrainTitle"));
219            initiateFrame.addHelpMenu("package.jmri.jmrit.dispatcher.NewTrain", true);
220            initiatePane = initiateFrame.getContentPane();
221            initiatePane.setLayout(new BoxLayout(initiatePane, BoxLayout.Y_AXIS));
222
223            // add buttons to load and save train information
224            JPanel p0 = new JPanel();
225            p0.setLayout(new FlowLayout());
226            p0.add(loadButton = new JButton(Bundle.getMessage("LoadButton")));
227            loadButton.addActionListener(new ActionListener() {
228                @Override
229                public void actionPerformed(ActionEvent e) {
230                    loadTrainInfo(e);
231                }
232            });
233            loadButton.setToolTipText(Bundle.getMessage("LoadButtonHint"));
234            p0.add(saveButton = new JButton(Bundle.getMessage("SaveButton")));
235            saveButton.addActionListener(new ActionListener() {
236                @Override
237                public void actionPerformed(ActionEvent e) {
238                    saveTrainInfo(e);
239                }
240            });
241            saveButton.setToolTipText(Bundle.getMessage("SaveButtonHint"));
242            p0.add(deleteButton = new JButton(Bundle.getMessage("DeleteButton")));
243            deleteButton.addActionListener(new ActionListener() {
244                @Override
245                public void actionPerformed(ActionEvent e) {
246                    deleteTrainInfo(e);
247                }
248            });
249            deleteButton.setToolTipText(Bundle.getMessage("DeleteButtonHint"));
250
251            // add items relating to both manually run and automatic trains.
252
253            // Trains From choices.
254            JPanel p0a = new JPanel();
255            p0a.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainsFrom")));
256            p0a.setLayout(new FlowLayout());
257            radioTrainsFromRoster.setActionCommand("TRAINSFROMROSTER");
258            trainsFromButtonGroup.add(radioTrainsFromRoster);
259            radioTrainsFromOps.setActionCommand("TRAINSFROMOPS");
260            trainsFromButtonGroup.add(radioTrainsFromOps);
261            radioTrainsFromUser.setActionCommand("TRAINSFROMUSER");
262            trainsFromButtonGroup.add(radioTrainsFromUser);
263            radioTrainsFromSetLater.setActionCommand("TRAINSFROMSETLATER");
264            trainsFromButtonGroup.add(radioTrainsFromSetLater);
265            p0a.add(radioTrainsFromRoster);
266            radioTrainsFromRoster.setToolTipText(Bundle.getMessage("TrainsFromRosterHint"));
267            p0a.add(radioTrainsFromOps);
268            radioTrainsFromOps.setToolTipText(Bundle.getMessage("TrainsFromTrainsHint"));
269            p0a.add(radioTrainsFromUser);
270            radioTrainsFromUser.setToolTipText(Bundle.getMessage("TrainsFromUserHint"));
271            p0a.add(radioTrainsFromSetLater);
272            radioTrainsFromSetLater.setToolTipText(Bundle.getMessage("TrainsFromSetLaterHint"));
273
274            radioTrainsFromOps.addItemListener(new ItemListener() {
275                @Override
276                public void itemStateChanged(ItemEvent e)  {
277                    if (e.getStateChange() == ItemEvent.SELECTED) {
278                        trainInfo.setTrainsFrom(TrainsFrom.TRAINSFROMOPS);
279                        setTrainsFromOptions(trainInfo.getTrainsFrom());
280                    }
281                }
282            });
283
284            radioTrainsFromRoster.addItemListener(new ItemListener() {
285                @Override
286                public void itemStateChanged(ItemEvent e)  {
287                    if (e.getStateChange() == ItemEvent.SELECTED) {
288                        trainInfo.setTrainsFrom(TrainsFrom.TRAINSFROMROSTER);
289                         setTrainsFromOptions(trainInfo.getTrainsFrom());
290                    }
291                }
292            });
293            radioTrainsFromUser.addItemListener(new ItemListener() {
294                @Override
295                public void itemStateChanged(ItemEvent e)  {
296                    if (e.getStateChange() == ItemEvent.SELECTED) {
297                        trainInfo.setTrainsFrom(TrainsFrom.TRAINSFROMUSER);
298                        setTrainsFromOptions(trainInfo.getTrainsFrom());
299                    }
300                }
301            });
302            radioTrainsFromSetLater.addItemListener(new ItemListener() {
303                @Override
304                public void itemStateChanged(ItemEvent e)  {
305                    if (e.getStateChange() == ItemEvent.SELECTED) {
306                        trainInfo.setTrainsFrom(TrainsFrom.TRAINSFROMSETLATER);
307                        setTrainsFromOptions(trainInfo.getTrainsFrom());
308                    }
309                }
310            });
311            p0a.add(allocateCustomSpinner);
312            initiatePane.add(p0a);
313
314            JPanel p1 = new JPanel();
315            p1.setLayout(new FlowLayout());
316            p1.add(new JLabel(Bundle.getMessage("TransitBoxLabel") + " :"));
317            p1.add(transitSelectBox);
318            transitSelectBox.addActionListener(new ActionListener() {
319                @Override
320                public void actionPerformed(ActionEvent e) {
321                    handleTransitSelectionChanged(e);
322                }
323            });
324            transitSelectBox.setToolTipText(Bundle.getMessage("TransitBoxHint"));
325            p1.add(trainBoxLabel);
326            p1.add(trainSelectBox);
327            trainSelectBox.addActionListener(new ActionListener() {
328                @Override
329                public void actionPerformed(ActionEvent e)  {
330                        handleTrainSelectionChanged();
331                }
332            });
333            trainSelectBox.setToolTipText(Bundle.getMessage("TrainBoxHint"));
334
335            rosterComboBox = new RosterEntryComboBox();
336            initializeFreeRosterEntriesCombo();
337            rosterComboBox.addActionListener(new ActionListener() {
338                @Override
339                public void actionPerformed(ActionEvent e) {
340                    handleRosterSelectionChanged(e);
341                }
342            });
343            p1.add(rosterComboBox);
344
345            initiatePane.add(p1);
346            JPanel p1a = new JPanel();
347            p1a.setLayout(new FlowLayout());
348            p1a.add(trainFieldLabel);
349            p1a.add(trainNameField);
350            trainNameField.setToolTipText(Bundle.getMessage("TrainFieldHint"));
351            p1a.add(dccAddressFieldLabel);
352            p1a.add(dccAddressSpinner);
353            dccAddressSpinner.setToolTipText(Bundle.getMessage("DccAddressFieldHint"));
354            initiatePane.add(p1a);
355            JPanel p2 = new JPanel();
356            p2.setLayout(new FlowLayout());
357            p2.add(inTransitBox);
358            inTransitBox.addActionListener(new ActionListener() {
359                @Override
360                public void actionPerformed(ActionEvent e) {
361                    handleInTransitClick(e);
362                }
363            });
364            inTransitBox.setToolTipText(Bundle.getMessage("InTransitBoxHint"));
365            initiatePane.add(p2);
366            JPanel p3 = new JPanel();
367            p3.setLayout(new FlowLayout());
368            p3.add(new JLabel(Bundle.getMessage("StartingBlockBoxLabel") + " :"));
369            p3.add(startingBlockBox);
370            startingBlockBox.setToolTipText(Bundle.getMessage("StartingBlockBoxHint"));
371            startingBlockBox.addActionListener(new ActionListener() {
372                @Override
373                public void actionPerformed(ActionEvent e) {
374                    handleStartingBlockSelectionChanged(e);
375                }
376            });
377            initiatePane.add(p3);
378            JPanel p4 = new JPanel();
379            p4.setLayout(new FlowLayout());
380            p4.add(new JLabel(Bundle.getMessage("DestinationBlockBoxLabel") + ":"));
381            p4.add(destinationBlockBox);
382            destinationBlockBox.setToolTipText(Bundle.getMessage("DestinationBlockBoxHint"));
383            JPanel p4a = new JPanel();
384            initiatePane.add(p4);
385            p4a.add(trainDetectionLabel);
386            initializeTrainDetectionBox();
387            p4a.add(trainDetectionComboBox);
388            trainDetectionComboBox.setToolTipText(Bundle.getMessage("TrainDetectionBoxHint"));
389            initiatePane.add(p4a);
390            JPanel p4b = new JPanel();
391            p4b.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AllocateMethodLabel")));
392            p4b.setLayout(new FlowLayout());
393            allocateMethodButtonGroup.add(allocateAllTheWayRadioButton);
394            allocateMethodButtonGroup.add(allocateBySafeRadioButton);
395            allocateMethodButtonGroup.add(allocateNumberOfBlocks);
396            p4b.add(allocateAllTheWayRadioButton);
397            allocateAllTheWayRadioButton.setToolTipText(Bundle.getMessage("AllocateAllTheWayHint"));
398            p4b.add(allocateBySafeRadioButton);
399            allocateBySafeRadioButton.setToolTipText(Bundle.getMessage("AllocateSafeHint"));
400            p4b.add(allocateNumberOfBlocks);
401            allocateNumberOfBlocks.setToolTipText(Bundle.getMessage("AllocateMethodHint"));
402            allocateAllTheWayRadioButton.addActionListener(new ActionListener() {
403                @Override
404                public void actionPerformed(ActionEvent e) {
405                    handleAllocateAllTheWayButtonChanged(e);
406                }
407            });
408            allocateBySafeRadioButton.addActionListener(new ActionListener() {
409                @Override
410                public void actionPerformed(ActionEvent e) {
411                    handleAllocateBySafeButtonChanged(e);
412                }
413            });
414            allocateNumberOfBlocks.addActionListener(new ActionListener() {
415                @Override
416                public void actionPerformed(ActionEvent e) {
417                    handleAllocateNumberOfBlocksButtonChanged(e);
418                }
419            });
420            p4b.add(allocateCustomSpinner);
421            allocateCustomSpinner.setToolTipText(Bundle.getMessage("AllocateMethodHint"));
422            initiatePane.add(p4b);
423            JPanel p6 = new JPanel();
424            p6.setLayout(new FlowLayout());
425            p6.add(resetWhenDoneBox);
426            resetWhenDoneBox.addActionListener(new ActionListener() {
427                @Override
428                public void actionPerformed(ActionEvent e) {
429                    handleResetWhenDoneClick(e);
430                }
431            });
432            resetWhenDoneBox.setToolTipText(Bundle.getMessage("ResetWhenDoneBoxHint"));
433            initiatePane.add(p6);
434            JPanel p6a = new JPanel();
435            p6a.setLayout(new FlowLayout());
436            ((FlowLayout) p6a.getLayout()).setVgap(1);
437            p6a.add(delayedReStartLabel);
438            p6a.add(delayedReStartBox);
439            p6a.add(resetRestartSensorBox);
440            resetRestartSensorBox.setToolTipText(Bundle.getMessage("ResetRestartSensorHint"));
441            resetRestartSensorBox.setSelected(true);
442            delayedReStartBox.addActionListener(new ActionListener() {
443                @Override
444                public void actionPerformed(ActionEvent e) {
445                    handleResetWhenDoneClick(e);
446                }
447            });
448            delayedReStartBox.setToolTipText(Bundle.getMessage("DelayedReStartHint"));
449            initiatePane.add(p6a);
450
451            JPanel p6b = new JPanel();
452            p6b.setLayout(new FlowLayout());
453            ((FlowLayout) p6b.getLayout()).setVgap(1);
454            p6b.add(delayMinLabel);
455            p6b.add(delayMinSpinner); // already set to 0
456            delayMinSpinner.setToolTipText(Bundle.getMessage("RestartTimedHint"));
457            p6b.add(delayReStartSensorLabel);
458            p6b.add(delayReStartSensor);
459            delayReStartSensor.setAllowNull(true);
460            handleResetWhenDoneClick(null);
461            initiatePane.add(p6b);
462
463            initiatePane.add(new JSeparator());
464
465            JPanel p10 = new JPanel();
466            p10.setLayout(new FlowLayout());
467            p10.add(reverseAtEndBox);
468            reverseAtEndBox.setToolTipText(Bundle.getMessage("ReverseAtEndBoxHint"));
469            initiatePane.add(p10);
470            reverseAtEndBox.addActionListener(new ActionListener() {
471                @Override
472                public void actionPerformed(ActionEvent e) {
473                    handleReverseAtEndBoxClick(e);
474                }
475            });
476            JPanel pDelayReverseRestartDetails = new JPanel();
477            pDelayReverseRestartDetails.setLayout(new FlowLayout());
478            ((FlowLayout) pDelayReverseRestartDetails.getLayout()).setVgap(1);
479            pDelayReverseRestartDetails.add(delayReverseReStartLabel);
480            pDelayReverseRestartDetails.add(reverseDelayedRestartType);
481            pDelayReverseRestartDetails.add(delayReverseResetSensorBox);
482            delayReverseResetSensorBox.setToolTipText(Bundle.getMessage("ReverseResetRestartSensorHint"));
483            delayReverseResetSensorBox.setSelected(true);
484            reverseDelayedRestartType.addActionListener(new ActionListener() {
485                @Override
486                public void actionPerformed(ActionEvent e) {
487                    handleReverseAtEndBoxClick(e);
488                }
489            });
490            reverseDelayedRestartType.setToolTipText(Bundle.getMessage("ReverseDelayedReStartHint"));
491            initiatePane.add(pDelayReverseRestartDetails);
492
493            JPanel pDelayReverseRestartDetails2 = new JPanel();
494            pDelayReverseRestartDetails2.setLayout(new FlowLayout());
495            ((FlowLayout) pDelayReverseRestartDetails2.getLayout()).setVgap(1);
496            pDelayReverseRestartDetails2.add(delayReverseMinLabel);
497            pDelayReverseRestartDetails2.add(delayReverseMinSpinner); // already set to 0
498            delayReverseMinSpinner.setToolTipText(Bundle.getMessage("ReverseRestartTimedHint"));
499            pDelayReverseRestartDetails2.add(delayReverseReStartSensorLabel);
500            pDelayReverseRestartDetails2.add(delayReverseReStartSensor);
501            delayReverseReStartSensor.setAllowNull(true);
502            handleReverseAtEndBoxClick(null);
503            initiatePane.add(pDelayReverseRestartDetails2);
504
505            initiatePane.add(new JSeparator());
506
507            JPanel p10a = new JPanel();
508            p10a.setLayout(new FlowLayout());
509            p10a.add(terminateWhenDoneBox);
510            terminateWhenDoneBox.addActionListener(new ActionListener() {
511                @Override
512                public void actionPerformed(ActionEvent e) {
513                    handleTerminateWhenDoneBoxClick(e);
514                }
515            });
516            initiatePane.add(p10a);
517            terminateWhenDoneDetails.setLayout(new FlowLayout());
518            terminateWhenDoneDetails.add(nextTrainLabel);
519            terminateWhenDoneDetails.add(nextTrain);
520            nextTrain.setToolTipText(Bundle.getMessage("TerminateWhenDoneNextTrainHint"));
521            initiatePane.add(terminateWhenDoneDetails);
522            handleTerminateWhenDoneBoxClick(null);
523
524            initiatePane.add(new JSeparator());
525
526            JPanel p8 = new JPanel();
527            p8.setLayout(new FlowLayout());
528            p8.add(new JLabel(Bundle.getMessage("PriorityLabel") + ":"));
529            p8.add(prioritySpinner); // already set to 5
530            prioritySpinner.setToolTipText(Bundle.getMessage("PriorityHint"));
531            p8.add(new JLabel("     "));
532            p8.add(new JLabel(Bundle.getMessage("TrainTypeBoxLabel")));
533            initializeTrainTypeBox();
534            p8.add(trainTypeBox);
535            trainTypeBox.setSelectedIndex(1);
536            trainTypeBox.setToolTipText(Bundle.getMessage("TrainTypeBoxHint"));
537            initiatePane.add(p8);
538            JPanel p9 = new JPanel();
539            p9.setLayout(new FlowLayout());
540            p9.add(new JLabel(Bundle.getMessage("DelayedStart")));
541            p9.add(delayedStartBox);
542            delayedStartBox.setToolTipText(Bundle.getMessage("DelayedStartHint"));
543            delayedStartBox.addActionListener(new ActionListener() {
544                @Override
545                public void actionPerformed(ActionEvent e) {
546                    handleDelayStartClick(e);
547                }
548            });
549            p9.add(departureTimeLabel);
550            departureHrSpinner.setEditor(new JSpinner.NumberEditor(departureHrSpinner, "00"));
551            p9.add(departureHrSpinner);
552            departureHrSpinner.setValue(8);
553            departureHrSpinner.setToolTipText(Bundle.getMessage("DepartureTimeHrHint"));
554            p9.add(departureSepLabel);
555            departureMinSpinner.setEditor(new JSpinner.NumberEditor(departureMinSpinner, "00"));
556            p9.add(departureMinSpinner);
557            departureMinSpinner.setValue(0);
558            departureMinSpinner.setToolTipText(Bundle.getMessage("DepartureTimeMinHint"));
559            p9.add(delaySensor);
560            delaySensor.setAllowNull(true);
561            p9.add(resetStartSensorBox);
562            resetStartSensorBox.setToolTipText(Bundle.getMessage("ResetStartSensorHint"));
563            resetStartSensorBox.setSelected(true);
564            handleDelayStartClick(null);
565            initiatePane.add(p9);
566
567            JPanel p11 = new JPanel();
568            p11.setLayout(new FlowLayout());
569            p11.add(loadAtStartupBox);
570            loadAtStartupBox.setToolTipText(Bundle.getMessage("LoadAtStartupBoxHint"));
571            loadAtStartupBox.setSelected(false);
572            initiatePane.add(p11);
573
574            initiatePane.add(new JSeparator());
575            JPanel p5 = new JPanel();
576            p5.setLayout(new FlowLayout());
577            p5.add(autoRunBox);
578            autoRunBox.addActionListener(new ActionListener() {
579                @Override
580                public void actionPerformed(ActionEvent e) {
581                    handleAutoRunClick(e);
582                }
583            });
584            autoRunBox.setToolTipText(Bundle.getMessage("AutoRunBoxHint"));
585            autoRunBox.setSelected(false);
586            initiatePane.add(p5);
587
588            initializeAutoRunItems();
589
590            JPanel p7 = new JPanel();
591            p7.setLayout(new FlowLayout());
592            JButton cancelButton = null;
593            p7.add(cancelButton = new JButton(Bundle.getMessage("ButtonCancel")));
594            cancelButton.addActionListener(new ActionListener() {
595                @Override
596                public void actionPerformed(ActionEvent e) {
597                    cancelInitiateTrain(e);
598                }
599            });
600            cancelButton.setToolTipText(Bundle.getMessage("CancelButtonHint"));
601            p7.add(addNewTrainButton = new JButton(Bundle.getMessage("ButtonCreate")));
602            addNewTrainButton.addActionListener(new ActionListener() {
603                @Override
604                public void actionPerformed(ActionEvent e) {
605                    addNewTrain(e);
606                }
607            });
608            addNewTrainButton.setToolTipText(Bundle.getMessage("AddNewTrainButtonHint"));
609
610            JPanel mainPane = new JPanel();
611            mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
612            JScrollPane scrPane = new JScrollPane(initiatePane);
613            mainPane.add(p0);
614            mainPane.add(scrPane);
615            mainPane.add(p7);
616            initiateFrame.setContentPane(mainPane);
617            switch (trainInfo.getTrainsFrom()) {
618                case TRAINSFROMROSTER:
619                    radioTrainsFromRoster.setSelected(true);
620                    break;
621                case TRAINSFROMOPS:
622                    radioTrainsFromOps.setSelected(true);
623                    break;
624                case TRAINSFROMUSER:
625                     radioTrainsFromUser.setSelected(true);
626                     break;
627                case TRAINSFROMSETLATER:
628                default:
629                    radioTrainsFromSetLater.setSelected(true);
630            }
631
632        }
633        autoRunBox.setSelected(false);
634        loadAtStartupBox.setSelected(false);
635        initializeFreeTransitsCombo(new ArrayList<Transit>());
636        nextTrain.addItem("");
637        refreshNextTrainCombo();
638        setTrainsFromOptions(trainInfo.getTrainsFrom());
639        initiateFrame.pack();
640        initiateFrame.setVisible(true);
641    }
642
643    private void refreshNextTrainCombo() {
644        Object saveEntry = null;
645        if (nextTrain.getSelectedIndex() > 0) {
646            saveEntry=nextTrain.getSelectedItem();
647        }
648        nextTrain.removeAll();
649        for (String file: _tiFile.getTrainInfoFileNames()) {
650            nextTrain.addItem(file);
651        }
652        if (saveEntry != null) {
653            nextTrain.setSelectedItem(saveEntry);
654        }
655    }
656    private void setTrainsFromOptions(TrainsFrom transFrom) {
657        switch (transFrom) {
658            case TRAINSFROMROSTER:
659                initializeFreeRosterEntriesCombo();
660                trainBoxLabel.setVisible(true);
661                rosterComboBox.setVisible(true);
662                trainSelectBox.setVisible(false);
663                trainFieldLabel.setVisible(true);
664                trainNameField.setVisible(true);
665                dccAddressFieldLabel.setVisible(false);
666                dccAddressSpinner.setVisible(false);
667                break;
668            case TRAINSFROMOPS:
669                initializeFreeTrainsCombo();
670                trainBoxLabel.setVisible(true);
671                trainSelectBox.setVisible(true);
672                rosterComboBox.setVisible(false);
673                trainFieldLabel.setVisible(true);
674                trainNameField.setVisible(true);
675                dccAddressFieldLabel.setVisible(true);
676                dccAddressSpinner.setVisible(true);
677                setSpeedProfileOptions(trainInfo,false);
678                break;
679            case TRAINSFROMUSER:
680                trainNameField.setText("");
681                trainBoxLabel.setVisible(false);
682                trainSelectBox.setVisible(false);
683                rosterComboBox.setVisible(false);
684                trainFieldLabel.setVisible(true);
685                trainNameField.setVisible(true);
686                dccAddressFieldLabel.setVisible(true);
687                dccAddressSpinner.setVisible(true);
688                dccAddressSpinner.setEnabled(true);
689                setSpeedProfileOptions(trainInfo,false);
690                break;
691            case TRAINSFROMSETLATER:
692            default:
693                trainBoxLabel.setVisible(false);
694                rosterComboBox.setVisible(false);
695                trainSelectBox.setVisible(false);
696                trainFieldLabel.setVisible(true);
697                trainNameField.setVisible(true);
698                dccAddressFieldLabel.setVisible(false);
699                dccAddressSpinner.setVisible(false);
700        }
701    }
702
703    private void initializeTrainTypeBox() {
704        trainTypeBox.removeAllItems();
705        trainTypeBox.addItem("<" + Bundle.getMessage("None").toLowerCase() + ">"); // <none>
706        trainTypeBox.addItem(Bundle.getMessage("LOCAL_PASSENGER"));
707        trainTypeBox.addItem(Bundle.getMessage("LOCAL_FREIGHT"));
708        trainTypeBox.addItem(Bundle.getMessage("THROUGH_PASSENGER"));
709        trainTypeBox.addItem(Bundle.getMessage("THROUGH_FREIGHT"));
710        trainTypeBox.addItem(Bundle.getMessage("EXPRESS_PASSENGER"));
711        trainTypeBox.addItem(Bundle.getMessage("EXPRESS_FREIGHT"));
712        trainTypeBox.addItem(Bundle.getMessage("MOW"));
713        // NOTE: The above must correspond in order and name to definitions in ActiveTrain.java.
714    }
715
716    private void initializeTrainDetectionBox() {
717        trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionWholeTrain"),TrainDetection.TRAINDETECTION_WHOLETRAIN));
718        trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionHeadAndTail"),TrainDetection.TRAINDETECTION_HEADANDTAIL));
719        trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionHeadOnly"),TrainDetection.TRAINDETECTION_HEADONLY));
720    }
721
722    private void handleTransitSelectionChanged(ActionEvent e) {
723        int index = transitSelectBox.getSelectedIndex();
724        if (index < 0) {
725            return;
726        }
727        Transit t = transitSelectBox.getSelectedItem();
728        if ((t != null) && (t != selectedTransit)) {
729            selectedTransit = t;
730            initializeStartingBlockCombo();
731            initializeDestinationBlockCombo();
732            initiateFrame.pack();
733        }
734    }
735
736    private void handleInTransitClick(ActionEvent e) {
737        if (!inTransitBox.isSelected() && selectedTransit.getEntryBlocksList().isEmpty()) {
738            JmriJOptionPane.showMessageDialog(initiateFrame, Bundle
739                    .getMessage("NoEntryBlocks"), Bundle.getMessage("MessageTitle"),
740                    JmriJOptionPane.INFORMATION_MESSAGE);
741            inTransitBox.setSelected(true);
742        }
743        initializeStartingBlockCombo();
744        initializeDestinationBlockCombo();
745        initiateFrame.pack();
746    }
747
748 //   private void handleTrainSelectionChanged(ActionEvent e) {
749      private void handleTrainSelectionChanged() {
750        if (trainInfo.getTrainsFrom() != TrainsFrom.TRAINSFROMOPS) {
751            return;
752        }
753        int ix = trainSelectBox.getSelectedIndex();
754        if (ix < 1) { // no train selected
755            dccAddressSpinner.setEnabled(false);
756            return;
757        }
758        dccAddressSpinner.setEnabled(true);
759        int dccAddress;
760        try {
761            dccAddress = Integer.parseInt((((Train) trainSelectBox.getSelectedItem()).getLeadEngineDccAddress()));
762        } catch (NumberFormatException Ex) {
763            JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error43"),
764                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
765            return;
766        }
767        dccAddressSpinner.setValue (dccAddress);
768    }
769
770    private void handleRosterSelectionChanged(ActionEvent e) {
771        if (trainInfo.getTrainsFrom() != TrainsFrom.TRAINSFROMROSTER) {
772            return;
773        }
774        int ix = rosterComboBox.getSelectedIndex();
775        if (ix > 0) { // first item is "Select Loco" string
776            RosterEntry r = (RosterEntry) rosterComboBox.getItemAt(ix);
777            // check to see if speed profile exists and is not empty
778            if (r.getSpeedProfile() == null || r.getSpeedProfile().getProfileSize() < 1) {
779                // disable profile boxes etc.
780                setSpeedProfileOptions(trainInfo,false);
781            } else {
782                // enable profile boxes
783                setSpeedProfileOptions(trainInfo,true);
784            }
785            trainInfo.setMaxSpeed(r.getMaxSpeedPCT()/100.0f);
786            maxSpeedSpinner.setValue(trainInfo.getMaxSpeed());
787            trainNameField.setText(r.titleString());
788            if (r.getAttribute("DispatcherTrainType") != null && !r.getAttribute("DispatcherTrainType").equals("")) {
789                trainTypeBox.setSelectedItem(r.getAttribute("DispatcherTrainType"));
790            }
791        } else {
792            setSpeedProfileOptions(trainInfo,false);
793        }
794    }
795
796    private void checkResetWhenDone() {
797        if ((!reverseAtEndBox.isSelected()) && resetWhenDoneBox.isSelected()
798                && (!selectedTransit.canBeResetWhenDone())) {
799            resetWhenDoneBox.setSelected(false);
800            throw new IllegalArgumentException(Bundle.getMessage("NoResetMessage"));
801        }
802    }
803
804    private void handleDelayStartClick(ActionEvent e) {
805        departureHrSpinner.setVisible(false);
806        departureMinSpinner.setVisible(false);
807        departureTimeLabel.setVisible(false);
808        departureSepLabel.setVisible(false);
809        delaySensor.setVisible(false);
810        resetStartSensorBox.setVisible(false);
811        if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) {
812            departureHrSpinner.setVisible(true);
813            departureMinSpinner.setVisible(true);
814            departureTimeLabel.setVisible(true);
815            departureSepLabel.setVisible(true);
816        } else if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) {
817            delaySensor.setVisible(true);
818            resetStartSensorBox.setVisible(true);
819        }
820        initiateFrame.pack(); // to fit extra hh:mm in window
821    }
822
823    private void handleResetWhenDoneClick(ActionEvent e) {
824        delayMinSpinner.setVisible(false);
825        delayMinLabel.setVisible(false);
826        delayedReStartLabel.setVisible(false);
827        delayedReStartBox.setVisible(false);
828        delayReStartSensorLabel.setVisible(false);
829        delayReStartSensor.setVisible(false);
830        resetRestartSensorBox.setVisible(false);
831        if (resetWhenDoneBox.isSelected()) {
832            delayedReStartLabel.setVisible(true);
833            delayedReStartBox.setVisible(true);
834            terminateWhenDoneBox.setSelected(false);
835            if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) {
836                delayMinSpinner.setVisible(true);
837                delayMinLabel.setVisible(true);
838            } else if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) {
839                delayReStartSensor.setVisible(true);
840                delayReStartSensorLabel.setVisible(true);
841                resetRestartSensorBox.setVisible(true);
842            }
843        } else {
844            terminateWhenDoneBox.setEnabled(true);
845        }
846        initiateFrame.pack();
847    }
848
849    private void handleTerminateWhenDoneBoxClick(ActionEvent e) {
850        if (terminateWhenDoneBox.isSelected()) {
851            refreshNextTrainCombo();
852            resetWhenDoneBox.setSelected(false);
853            terminateWhenDoneDetails.setVisible(true);
854        } else {
855            terminateWhenDoneDetails.setVisible(false);
856            // leave it
857            //nextTrain.setSelectedItem("");
858        }
859    }
860    private void handleReverseAtEndBoxClick(ActionEvent e) {
861        delayReverseMinSpinner.setVisible(false);
862        delayReverseMinLabel.setVisible(false);
863        delayReverseReStartLabel.setVisible(false);
864        reverseDelayedRestartType.setVisible(false);
865        delayReverseReStartSensorLabel.setVisible(false);
866        delayReverseReStartSensor.setVisible(false);
867        delayReverseResetSensorBox.setVisible(false);
868        if (reverseAtEndBox.isSelected()) {
869            delayReverseReStartLabel.setVisible(true);
870            reverseDelayedRestartType.setVisible(true);
871            if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) {
872                delayReverseMinSpinner.setVisible(true);
873                delayReverseMinLabel.setVisible(true);
874            } else if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) {
875                delayReverseReStartSensor.setVisible(true);
876                delayReStartSensorLabel.setVisible(true);
877                delayReverseResetSensorBox.setVisible(true);
878            }
879        }
880        initiateFrame.pack();
881
882        if (resetWhenDoneBox.isSelected()) {
883            terminateWhenDoneBox.setSelected(false);
884            terminateWhenDoneBox.setEnabled(false);
885        } else {
886            terminateWhenDoneBox.setEnabled(true);
887        }
888    }
889
890    private void handleAutoRunClick(ActionEvent e) {
891        if (autoRunBox.isSelected()) {
892            showAutoRunItems();
893        } else {
894            hideAutoRunItems();
895        }
896        initiateFrame.pack();
897    }
898
899    private void handleStartingBlockSelectionChanged(ActionEvent e) {
900        initializeDestinationBlockCombo();
901        initiateFrame.pack();
902    }
903
904    private void handleAllocateAllTheWayButtonChanged(ActionEvent e) {
905        allocateCustomSpinner.setVisible(false);
906    }
907
908    private void handleAllocateBySafeButtonChanged(ActionEvent e) {
909        allocateCustomSpinner.setVisible(false);
910    }
911
912    private void handleAllocateNumberOfBlocksButtonChanged(ActionEvent e) {
913        allocateCustomSpinner.setVisible(true);
914    }
915
916    private void cancelInitiateTrain(ActionEvent e) {
917        _dispatcher.newTrainDone(null);
918    }
919
920    /*
921     * Handles press of "Add New Train" button.
922     * Move data to TrainInfo validating basic information
923     * Call dispatcher to start the train from traininfo which
924     * completes validation.
925     */
926    private void addNewTrain(ActionEvent e) {
927        try {
928            dialogToTrainInfo(trainInfo);
929            _dispatcher.loadTrainFromTrainInfoThrowsException(trainInfo,"NONE","");
930        } catch (IllegalArgumentException ex) {
931            JmriJOptionPane.showMessageDialog(initiateFrame, ex.getMessage(),
932                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
933        }
934    }
935
936    private void initializeFreeTransitsCombo(List<Transit> transitList) {
937        Set<Transit> excludeTransits = new HashSet<>();
938        for (Transit t : _TransitManager.getNamedBeanSet()) {
939            if (t.getState() != Transit.IDLE) {
940                excludeTransits.add(t);
941            }
942        }
943        transitSelectBox.setExcludedItems(excludeTransits);
944        JComboBoxUtil.setupComboBoxMaxRows(transitSelectBox);
945
946        if (transitSelectBox.getItemCount() > 0) {
947            transitSelectBox.setSelectedIndex(0);
948            selectedTransit = transitSelectBox.getItemAt(0);
949        } else {
950            selectedTransit = null;
951        }
952    }
953
954    private void initializeFreeRosterEntriesCombo() {
955        rosterComboBox.update();
956        // remove used entries
957        for (int ix = rosterComboBox.getItemCount() - 1; ix > 1; ix--) {  // remove from back first item is the "select loco" message
958            if ( !_dispatcher.isAddressFree( ((RosterEntry)rosterComboBox.getItemAt(ix)).getDccLocoAddress().getNumber() ) ) {
959                rosterComboBox.removeItemAt(ix);
960            }
961        }
962    }
963
964    private void initializeFreeTrainsCombo() {
965        ActionListener[] als = trainSelectBox.getActionListeners();
966        for ( ActionListener al: als) {
967            trainSelectBox.removeActionListener(al);
968        }
969        trainSelectBox.removeAllItems();
970        trainSelectBox.addItem("Select Train");
971        // initialize free trains from operations
972        List<Train> trains = jmri.InstanceManager.getDefault(TrainManager.class).getTrainsByNameList();
973        if (trains.size() > 0) {
974            for (int i = 0; i < trains.size(); i++) {
975                Train t = trains.get(i);
976                if (t != null) {
977                    String tName = t.getName();
978                    if (_dispatcher.isTrainFree(tName)) {
979                        trainSelectBox.addItem(t);
980                    }
981                }
982            }
983        }
984        for ( ActionListener al: als) {
985            trainSelectBox.addActionListener(al);
986        }
987    }
988
989    /**
990     * Sets the labels and inputs for speed profile running
991     * @param b True if the roster entry has valid speed profile else false
992     */
993    private void setSpeedProfileOptions(TrainInfo info,boolean b) {
994        useSpeedProfileLabel.setEnabled(b);
995        useSpeedProfileCheckBox.setEnabled(b);
996        stopBySpeedProfileLabel.setEnabled(b);
997        stopBySpeedProfileCheckBox.setEnabled(b);
998        stopBySpeedProfileAdjustLabel.setEnabled(b);
999        stopBySpeedProfileAdjustSpinner.setEnabled(b);
1000        if (!b) {
1001            useSpeedProfileCheckBox.setSelected(false);
1002            stopBySpeedProfileCheckBox.setSelected(false);
1003            info.setUseSpeedProfile(false);
1004            info.setStopBySpeedProfile(false);
1005        }
1006    }
1007
1008
1009
1010    private void initializeStartingBlockCombo() {
1011        startingBlockBox.removeAllItems();
1012        startingBlockBoxList.clear();
1013        if (!inTransitBox.isSelected() && selectedTransit.getEntryBlocksList().isEmpty()) {
1014            inTransitBox.setSelected(true);
1015        }
1016        if (inTransitBox.isSelected()) {
1017            startingBlockBoxList = selectedTransit.getInternalBlocksList();
1018        } else {
1019            startingBlockBoxList = selectedTransit.getEntryBlocksList();
1020        }
1021        startingBlockSeqList = selectedTransit.getBlockSeqList();
1022        boolean found = false;
1023        for (int i = 0; i < startingBlockBoxList.size(); i++) {
1024            Block b = startingBlockBoxList.get(i);
1025            int seq = startingBlockSeqList.get(i).intValue();
1026            startingBlockBox.addItem(getBlockName(b) + "-" + seq);
1027            if (!found && b.getState() == Block.OCCUPIED) {
1028                startingBlockBox.setSelectedItem(getBlockName(b) + "-" + seq);
1029                found = true;
1030            }
1031        }
1032        JComboBoxUtil.setupComboBoxMaxRows(startingBlockBox);
1033    }
1034
1035    private void initializeDestinationBlockCombo() {
1036        destinationBlockBox.removeAllItems();
1037        destinationBlockBoxList.clear();
1038        int index = startingBlockBox.getSelectedIndex();
1039        if (index < 0) {
1040            return;
1041        }
1042        Block startBlock = startingBlockBoxList.get(index);
1043        destinationBlockBoxList = selectedTransit.getDestinationBlocksList(
1044                startBlock, inTransitBox.isSelected());
1045        destinationBlockSeqList = selectedTransit.getDestBlocksSeqList();
1046        for (int i = 0; i < destinationBlockBoxList.size(); i++) {
1047            Block b = destinationBlockBoxList.get(i);
1048            String bName = getBlockName(b);
1049            if (selectedTransit.getBlockCount(b) > 1) {
1050                int seq = destinationBlockSeqList.get(i).intValue();
1051                bName = bName + "-" + seq;
1052            }
1053            destinationBlockBox.addItem(bName);
1054        }
1055        JComboBoxUtil.setupComboBoxMaxRows(destinationBlockBox);
1056    }
1057
1058    private String getBlockName(Block b) {
1059        if (b != null) {
1060            return b.getDisplayName();
1061        }
1062        return " ";
1063    }
1064
1065    protected void showActivateFrame() {
1066        if (initiateFrame != null) {
1067            initializeFreeTransitsCombo(new ArrayList<Transit>());
1068            initiateFrame.setVisible(true);
1069        } else {
1070            _dispatcher.newTrainDone(null);
1071        }
1072    }
1073
1074    public void showActivateFrame(RosterEntry re) {
1075        showActivateFrame();
1076    }
1077
1078    private void loadTrainInfo(ActionEvent e) {
1079        String[] names = _tiFile.getTrainInfoFileNames();
1080        TrainInfo info = null;
1081        if (names.length > 0) {
1082            //prompt user to select a single train info filename from directory list
1083            Object selName = JmriJOptionPane.showInputDialog(initiateFrame,
1084                    Bundle.getMessage("LoadTrainChoice"), Bundle.getMessage("LoadTrainTitle"),
1085                    JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]);
1086            if ((selName == null) || (((String) selName).equals(""))) {
1087                return;
1088            }
1089            //read xml data from selected filename and move it into the new train dialog box
1090            _trainInfoName = (String) selName;
1091            try {
1092                info = _tiFile.readTrainInfo((String) selName);
1093                if (info != null) {
1094                    // process the information just read
1095                    trainInfoToDialog(info);
1096                }
1097            } catch (java.io.IOException ioe) {
1098                log.error("IO Exception when reading train info file", ioe);
1099            } catch (org.jdom2.JDOMException jde) {
1100                log.error("JDOM Exception when reading train info file", jde);
1101            }
1102        }
1103        handleDelayStartClick(null);
1104        handleReverseAtEndBoxClick(null);
1105    }
1106
1107    private void saveTrainInfo(ActionEvent e) {
1108        trainInfo=new TrainInfo();
1109        try {
1110            dialogToTrainInfo(trainInfo);
1111        } catch (IllegalArgumentException ide) {
1112            JmriJOptionPane.showMessageDialog(initiateFrame, ide.getMessage(),
1113                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1114            return;
1115        }
1116        // get file name
1117        String eName = "";
1118        eName = JmriJOptionPane.showInputDialog(initiateFrame,
1119                Bundle.getMessage("EnterFileName") + " :", _trainInfoName);
1120        if (eName == null) {  //Cancel pressed
1121            return;
1122        }
1123        if (eName.length() < 1) {
1124            JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error25"),
1125                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
1126            return;
1127        }
1128        String fileName = normalizeXmlFileName(eName);
1129        _trainInfoName = fileName;
1130        // check if train info file name is in use
1131        String[] names = _tiFile.getTrainInfoFileNames();
1132        if (names.length > 0) {
1133            boolean found = false;
1134            for (int i = 0; i < names.length; i++) {
1135                if (fileName.equals(names[i])) {
1136                    found = true;
1137                }
1138            }
1139            if (found) {
1140                // file by that name is already present
1141                int selectedValue = JmriJOptionPane.showOptionDialog(initiateFrame,
1142                        Bundle.getMessage("Question3", fileName),
1143                        Bundle.getMessage("WarningTitle"), JmriJOptionPane.DEFAULT_OPTION,
1144                        JmriJOptionPane.QUESTION_MESSAGE, null,
1145                        new Object[]{Bundle.getMessage("ButtonReplace"),Bundle.getMessage("ButtonNo")},
1146                        Bundle.getMessage("ButtonNo"));
1147                if (selectedValue != 0 ) { // array position 0 , replace not selected
1148                    return;   // return without writing if "No" response
1149                }
1150            }
1151        }
1152        // write the Train Info file
1153        try {
1154            _tiFile.writeTrainInfo(trainInfo, fileName);
1155        } //catch (org.jdom2.JDOMException jde) {
1156        // log.error("JDOM exception writing Train Info: "+jde);
1157        //}
1158        catch (java.io.IOException ioe) {
1159            log.error("IO exception writing Train Info", ioe);
1160        }
1161    }
1162
1163    private void deleteTrainInfo(ActionEvent e) {
1164        String[] names = _tiFile.getTrainInfoFileNames();
1165        if (names.length > 0) {
1166            Object selName = JmriJOptionPane.showInputDialog(initiateFrame,
1167                    Bundle.getMessage("DeleteTrainChoice"), Bundle.getMessage("DeleteTrainTitle"),
1168                    JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]);
1169            if ((selName == null) || (((String) selName).equals(""))) {
1170                return;
1171            }
1172            _tiFile.deleteTrainInfoFile((String) selName);
1173        }
1174    }
1175
1176    private void trainInfoToDialog(TrainInfo info) {
1177        try {
1178            transitSelectBox.setSelectedItemByName(info.getTransitName());
1179        } catch (Exception ex) {
1180            log.warn("Transit {} from file not in Transit menu", info.getTransitName());
1181            JmriJOptionPane.showMessageDialog(initiateFrame,
1182                    Bundle.getMessage("TransitWarn", info.getTransitName()),
1183                    null, JmriJOptionPane.WARNING_MESSAGE);
1184        }
1185        switch (info.getTrainsFrom()) {
1186            case TRAINSFROMROSTER:
1187                radioTrainsFromRoster.setSelected(true);
1188                if (!setRosterComboBox(rosterComboBox, info.getRosterId())) {
1189                    log.warn("Roster {} from file not in Roster Combo", info.getRosterId());
1190                    JmriJOptionPane.showMessageDialog(initiateFrame,
1191                            Bundle.getMessage("TrainWarn", info.getRosterId()),
1192                            null, JmriJOptionPane.WARNING_MESSAGE);
1193                }
1194                break;
1195            case TRAINSFROMOPS:
1196                radioTrainsFromOps.setSelected(true);
1197                if (!setTrainComboBox(trainSelectBox, info.getTrainName())) {
1198                    log.warn("Train {} from file not in Train Combo", info.getTrainName());
1199                    JmriJOptionPane.showMessageDialog(initiateFrame,
1200                            Bundle.getMessage("TrainWarn", info.getTrainName()),
1201                            null, JmriJOptionPane.WARNING_MESSAGE);
1202                }
1203                break;
1204            case TRAINSFROMUSER:
1205                radioTrainsFromUser.setSelected(true);
1206                dccAddressSpinner.setValue(Integer.parseInt(info.getDccAddress()));
1207                break;
1208            case TRAINSFROMSETLATER:
1209            default:
1210                radioTrainsFromSetLater.setSelected(true);
1211        }
1212        trainNameField.setText(info.getTrainUserName());
1213        trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection());
1214        inTransitBox.setSelected(info.getTrainInTransit());
1215        initializeStartingBlockCombo();
1216        initializeDestinationBlockCombo();
1217        setComboBox(startingBlockBox, info.getStartBlockName());
1218        setComboBox(destinationBlockBox, info.getDestinationBlockName());
1219        setAllocateMethodButtons(info.getAllocationMethod());
1220        prioritySpinner.setValue(info.getPriority());
1221        resetWhenDoneBox.setSelected(info.getResetWhenDone());
1222        reverseAtEndBox.setSelected(info.getReverseAtEnd());
1223        setDelayModeBox(info.getDelayedStart(), delayedStartBox);
1224        //delayedStartBox.setSelected(info.getDelayedStart());
1225        departureHrSpinner.setValue(info.getDepartureTimeHr());
1226        departureMinSpinner.setValue(info.getDepartureTimeMin());
1227        delaySensor.setSelectedItem(info.getDelaySensor());
1228        resetStartSensorBox.setSelected(info.getResetStartSensor());
1229        setDelayModeBox(info.getDelayedRestart(), delayedReStartBox);
1230        delayMinSpinner.setValue(info.getRestartDelayMin());
1231        delayReStartSensor.setSelectedItem(info.getRestartSensor());
1232        resetRestartSensorBox.setSelected(info.getResetRestartSensor());
1233
1234        resetStartSensorBox.setSelected(info.getResetStartSensor());
1235        setDelayModeBox(info.getReverseDelayedRestart(), reverseDelayedRestartType);
1236        delayReverseMinSpinner.setValue(info.getReverseRestartDelayMin());
1237        delayReverseReStartSensor.setSelectedItem(info.getReverseRestartSensor());
1238        delayReverseResetSensorBox.setSelected(info.getReverseResetRestartSensor());
1239
1240        terminateWhenDoneBox.setSelected(info.getTerminateWhenDone());
1241        nextTrain.setSelectedIndex(-1);
1242
1243        try {
1244            nextTrain.setSelectedItem(info.getNextTrain());
1245        } catch (Exception ex){
1246            nextTrain.setSelectedIndex(-1);
1247        }
1248        handleTerminateWhenDoneBoxClick(null);
1249        setComboBox(trainTypeBox, info.getTrainType());
1250        autoRunBox.setSelected(info.getAutoRun());
1251        loadAtStartupBox.setSelected(info.getLoadAtStartup());
1252        setAllocateMethodButtons(info.getAllocationMethod());
1253        autoTrainInfoToDialog(info);
1254    }
1255
1256    private boolean dialogToTrainInfo(TrainInfo info) throws IllegalArgumentException {
1257        int index = transitSelectBox.getSelectedIndex();
1258        if (index < 0) {
1259            throw new IllegalArgumentException(Bundle.getMessage("Error44"));
1260        } else {
1261            info.setTransitName(transitSelectBox.getSelectedItem().getDisplayName());
1262            info.setTransitId(transitSelectBox.getSelectedItem().getDisplayName());
1263        }
1264        switch (trainsFromButtonGroup.getSelection().getActionCommand()) {
1265            case "TRAINSFROMROSTER":
1266                if (rosterComboBox.getSelectedIndex() < 1 ) {
1267                    throw new IllegalArgumentException(Bundle.getMessage("Error41"));
1268                }
1269                info.setRosterId(((RosterEntry) rosterComboBox.getSelectedItem()).getId());
1270                info.setDccAddress(((RosterEntry) rosterComboBox.getSelectedItem()).getDccAddress());
1271                break;
1272            case "TRAINSFROMOPS":
1273                if (trainSelectBox.getSelectedIndex() < 1) {
1274                    throw new IllegalArgumentException(Bundle.getMessage("Error42"));
1275                }
1276                info.setTrainName(((Train) trainSelectBox.getSelectedItem()).getId());
1277                info.setDccAddress(String.valueOf(dccAddressSpinner.getValue()));
1278                break;
1279            case "TRAINSFROMUSER":
1280                if (trainNameField.getText().isEmpty()) {
1281                    throw new IllegalArgumentException(Bundle.getMessage("Error22"));
1282                }
1283                info.setDccAddress(String.valueOf(dccAddressSpinner.getValue()));
1284                break;
1285            case "TRAINSFROMSETLATER":
1286            default:
1287                info.setTrainName("");
1288                info.setDccAddress("");
1289        }
1290        info.setTrainUserName(trainNameField.getText());
1291        info.setTrainInTransit(inTransitBox.isSelected());
1292        info.setStartBlockName((String) startingBlockBox.getSelectedItem());
1293        index = startingBlockBox.getSelectedIndex();
1294        if (index < 0) {
1295            throw new IllegalArgumentException(Bundle.getMessage("Error13"));
1296        } else {
1297            info.setStartBlockId(startingBlockBoxList.get(index).getDisplayName());
1298            info.setStartBlockSeq(startingBlockSeqList.get(index).intValue());
1299        }
1300        info.setDestinationBlockName((String) destinationBlockBox.getSelectedItem());
1301        index = destinationBlockBox.getSelectedIndex();
1302        if (index < 0) {
1303            throw new IllegalArgumentException(Bundle.getMessage("Error8"));
1304        } else {
1305            info.setDestinationBlockId(destinationBlockBoxList.get(index).getDisplayName());
1306            info.setDestinationBlockSeq(destinationBlockSeqList.get(index).intValue());
1307        }
1308        checkResetWhenDone();
1309        info.setPriority((Integer) prioritySpinner.getValue());
1310        info.setTrainDetection(((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value);
1311        info.setResetWhenDone(resetWhenDoneBox.isSelected());
1312        info.setReverseAtEnd(reverseAtEndBox.isSelected());
1313        info.setDelayedStart(delayModeFromBox(delayedStartBox));
1314        info.setDelaySensorName(delaySensor.getSelectedItemDisplayName());
1315        info.setResetStartSensor(resetStartSensorBox.isSelected());
1316        info.setDepartureTimeHr((Integer) departureHrSpinner.getValue());
1317        info.setDepartureTimeMin((Integer) departureMinSpinner.getValue());
1318        info.setTrainType((String) trainTypeBox.getSelectedItem());
1319        info.setAutoRun(autoRunBox.isSelected());
1320        info.setLoadAtStartup(loadAtStartupBox.isSelected());
1321        info.setAllocateAllTheWay(false); // force to false next field is now used.
1322        if (allocateAllTheWayRadioButton.isSelected()) {
1323            info.setAllocationMethod(ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN);
1324        } else if (allocateBySafeRadioButton.isSelected()) {
1325            info.setAllocationMethod(ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS);
1326        } else {
1327            info.setAllocationMethod((Integer) allocateCustomSpinner.getValue());
1328        }
1329        info.setDelayedRestart(delayModeFromBox(delayedReStartBox));
1330        info.setRestartSensorName(delayReStartSensor.getSelectedItemDisplayName());
1331        info.setResetRestartSensor(resetRestartSensorBox.isSelected());
1332        info.setRestartDelayMin((Integer) delayMinSpinner.getValue());
1333
1334        info.setReverseDelayedRestart(delayModeFromBox(reverseDelayedRestartType));
1335        info.setReverseRestartSensorName(delayReverseReStartSensor.getSelectedItemDisplayName());
1336        info.setReverseResetRestartSensor(delayReverseResetSensorBox.isSelected());
1337        info.setReverseRestartDelayMin((Integer) delayReverseMinSpinner.getValue());
1338
1339        info.setTerminateWhenDone(terminateWhenDoneBox.isSelected());
1340        if (nextTrain.getSelectedIndex() > 0 ) {
1341            info.setNextTrain((String)nextTrain.getSelectedItem());
1342        } else {
1343            info.setNextTrain("None");
1344        }
1345        autoRunItemsToTrainInfo(info);
1346        return true;
1347    }
1348
1349    private boolean setRosterComboBox(RosterEntryComboBox box, String txt) {
1350        boolean found = false;
1351        for (int i = 1; i < box.getItemCount(); i++) {
1352            if (txt.equals(((RosterEntry) box.getItemAt(i)).getId())) {
1353                box.setSelectedIndex(i);
1354                found = true;
1355                break;
1356            }
1357        }
1358        if (!found && box.getItemCount() > 0) {
1359            box.setSelectedIndex(0);
1360        }
1361        return found;
1362    }
1363
1364    // Normalizes a suggested xml file name.  Returns null string if a valid name cannot be assembled
1365    private String normalizeXmlFileName(String name) {
1366        if (name.length() < 1) {
1367            return "";
1368        }
1369        String newName = name;
1370        // strip off .xml or .XML if present
1371        if ((name.endsWith(".xml")) || (name.endsWith(".XML"))) {
1372            newName = name.substring(0, name.length() - 4);
1373            if (newName.length() < 1) {
1374                return "";
1375            }
1376        }
1377        // replace all non-alphanumeric characters with underscore
1378        newName = newName.replaceAll("[\\W]", "_");
1379        return (newName + ".xml");
1380    }
1381
1382    private boolean setTrainComboBox(JComboBox<Object> box, String txt) {
1383        boolean found = false;
1384        for (int i = 1; i < box.getItemCount(); i++) { //skip the select train item
1385            if (txt.equals(box.getItemAt(i).toString())) {
1386                box.setSelectedIndex(i);
1387                found = true;
1388                break;
1389            }
1390        }
1391        if (!found && box.getItemCount() > 0) {
1392            box.setSelectedIndex(0);
1393        }
1394        return found;
1395    }
1396
1397    private boolean setComboBox(JComboBox<String> box, String txt) {
1398        boolean found = false;
1399        for (int i = 0; i < box.getItemCount(); i++) {
1400            if (txt.equals(box.getItemAt(i))) {
1401                box.setSelectedIndex(i);
1402                found = true;
1403                break;
1404            }
1405        }
1406        if (!found && box.getItemCount() > 0) {
1407            box.setSelectedIndex(0);
1408        }
1409        return found;
1410    }
1411
1412    int delayModeFromBox(JComboBox<String> box) {
1413        String mode = (String) box.getSelectedItem();
1414        int result = jmri.util.StringUtil.getStateFromName(mode, delayedStartInt, delayedStartString);
1415
1416        if (result < 0) {
1417            log.warn("unexpected mode string in turnoutMode: {}", mode);
1418            throw new IllegalArgumentException();
1419        }
1420        return result;
1421    }
1422
1423    void setDelayModeBox(int mode, JComboBox<String> box) {
1424        String result = jmri.util.StringUtil.getNameFromState(mode, delayedStartInt, delayedStartString);
1425        box.setSelectedItem(result);
1426    }
1427
1428    /**
1429     * The following are for items that are only for automatic running of
1430     * ActiveTrains They are isolated here to simplify changing them in the
1431     * future.
1432     * <ul>
1433     * <li>initializeAutoRunItems - initializes the display of auto run items in
1434     * this window
1435     * <li>initializeAutoRunValues - initializes the values of auto run items
1436     * from values in a saved train info file hideAutoRunItems - hides all auto
1437     * run items in this window showAutoRunItems - shows all auto run items in
1438     * this window
1439     * <li>autoTrainInfoToDialog - gets auto run items from a train info, puts
1440     * values in items, and initializes auto run dialog items
1441     * <li>autoTrainItemsToTrainInfo - copies values of auto run items to train
1442     * info for saving to a file
1443     * <li>readAutoRunItems - reads and checks values of all auto run items.
1444     * returns true if OK, sends appropriate messages and returns false if not
1445     * OK
1446     * <li>setAutoRunItems - sets the user entered auto run items in the new
1447     * AutoActiveTrain
1448     * </ul>
1449     */
1450    // auto run items in ActivateTrainFrame
1451    private final JPanel pa1 = new JPanel();
1452    private final JLabel speedFactorLabel = new JLabel(Bundle.getMessage("SpeedFactorLabel"));
1453    private final JSpinner speedFactorSpinner = new JSpinner();
1454    private final JLabel minReliableOperatingSpeedLabel = new JLabel(Bundle.getMessage("MinReliableOperatingSpeedLabel"));
1455    private final JSpinner minReliableOperatingSpeedSpinner = new JSpinner();
1456    private final JLabel maxSpeedLabel = new JLabel(Bundle.getMessage("MaxSpeedLabel"));
1457    private final JSpinner maxSpeedSpinner = new JSpinner();
1458    private final JPanel pa2 = new JPanel();
1459    private final JLabel rampRateLabel = new JLabel(Bundle.getMessage("RampRateBoxLabel"));
1460    private final JComboBox<String> rampRateBox = new JComboBox<>();
1461    private final JPanel pa2a = new JPanel();
1462    private final JLabel useSpeedProfileLabel = new JLabel(Bundle.getMessage("UseSpeedProfileLabel"));
1463    private final JCheckBox useSpeedProfileCheckBox = new JCheckBox( );
1464    private final JLabel stopBySpeedProfileLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileLabel"));
1465    private final JCheckBox stopBySpeedProfileCheckBox = new JCheckBox( );
1466    private final JLabel stopBySpeedProfileAdjustLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileAdjustLabel"));
1467    private final JSpinner stopBySpeedProfileAdjustSpinner = new JSpinner();
1468    private final JPanel pa3 = new JPanel();
1469    private final JCheckBox soundDecoderBox = new JCheckBox(Bundle.getMessage("SoundDecoder"));
1470    private final JCheckBox runInReverseBox = new JCheckBox(Bundle.getMessage("RunInReverse"));
1471    private final JPanel pa4 = new JPanel();
1472    protected static class TrainDetectionJCombo extends JComboBox<TrainDetectionItem> {
1473        public void setSelectedItemByValue(TrainDetection var) {
1474            for ( int ix = 0; ix < getItemCount() ; ix ++ ) {
1475                if (getItemAt(ix).value == var) {
1476                    this.setSelectedIndex(ix);
1477                    break;
1478                }
1479            }
1480        }
1481    }
1482    public final TrainDetectionJCombo trainDetectionComboBox
1483                = new TrainDetectionJCombo();
1484    private final JLabel trainDetectionLabel = new JLabel(Bundle.getMessage("TrainDetection"));
1485    private final JLabel trainLengthLabel = new JLabel(Bundle.getMessage("MaxTrainLengthLabel"));
1486    private final JSpinner maxTrainLengthSpinner = new JSpinner(); // initialized later
1487
1488    private void initializeAutoRunItems() {
1489        initializeRampCombo();
1490        pa1.setLayout(new FlowLayout());
1491        pa1.add(speedFactorLabel);
1492        speedFactorSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(2.0f), Float.valueOf(0.01f)));
1493        speedFactorSpinner.setEditor(new JSpinner.NumberEditor(speedFactorSpinner, "# %"));
1494        pa1.add(speedFactorSpinner);
1495        speedFactorSpinner.setToolTipText(Bundle.getMessage("SpeedFactorHint"));
1496        pa1.add(new JLabel("   "));
1497        pa1.add(maxSpeedLabel);
1498        maxSpeedSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(1.0f), Float.valueOf(0.01f)));
1499        maxSpeedSpinner.setEditor(new JSpinner.NumberEditor(maxSpeedSpinner, "# %"));
1500        pa1.add(maxSpeedSpinner);
1501        maxSpeedSpinner.setToolTipText(Bundle.getMessage("MaxSpeedHint"));
1502        pa1.add(minReliableOperatingSpeedLabel);
1503        minReliableOperatingSpeedSpinner.setModel(new SpinnerNumberModel(Float.valueOf(0.0f), Float.valueOf(0.0f), Float.valueOf(1.0f), Float.valueOf(0.01f)));
1504        minReliableOperatingSpeedSpinner.setEditor(new JSpinner.NumberEditor(minReliableOperatingSpeedSpinner, "# %"));
1505        pa1.add(minReliableOperatingSpeedSpinner);
1506        minReliableOperatingSpeedSpinner.setToolTipText(Bundle.getMessage("MinReliableOperatingSpeedHint"));
1507        initiatePane.add(pa1);
1508        pa2.setLayout(new FlowLayout());
1509        pa2.add(rampRateLabel);
1510        pa2.add(rampRateBox);
1511        rampRateBox.setToolTipText(Bundle.getMessage("RampRateBoxHint"));
1512        pa2.add(useSpeedProfileLabel);
1513        pa2.add(useSpeedProfileCheckBox);
1514        useSpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint"));
1515        initiatePane.add(pa2);
1516        pa2a.setLayout(new FlowLayout());
1517        pa2a.add(stopBySpeedProfileLabel);
1518        pa2a.add(stopBySpeedProfileCheckBox);
1519        stopBySpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint")); // reuse identical hint for Stop
1520        pa2a.add(stopBySpeedProfileAdjustLabel);
1521        stopBySpeedProfileAdjustSpinner.setModel(new SpinnerNumberModel( Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(5.0f), Float.valueOf(0.01f)));
1522        stopBySpeedProfileAdjustSpinner.setEditor(new JSpinner.NumberEditor(stopBySpeedProfileAdjustSpinner, "# %"));
1523        pa2a.add(stopBySpeedProfileAdjustSpinner);
1524        stopBySpeedProfileAdjustSpinner.setToolTipText(Bundle.getMessage("StopBySpeedProfileAdjustHint"));
1525        initiatePane.add(pa2a);
1526        pa3.setLayout(new FlowLayout());
1527        pa3.add(soundDecoderBox);
1528        soundDecoderBox.setToolTipText(Bundle.getMessage("SoundDecoderBoxHint"));
1529        pa3.add(new JLabel("   "));
1530        pa3.add(runInReverseBox);
1531        runInReverseBox.setToolTipText(Bundle.getMessage("RunInReverseBoxHint"));
1532        initiatePane.add(pa3);
1533        pa4.setLayout(new FlowLayout());
1534        pa4.add(trainLengthLabel);
1535        maxTrainLengthSpinner.setModel(new SpinnerNumberModel(Float.valueOf(18.0f), Float.valueOf(0.0f), Float.valueOf(10000.0f), Float.valueOf(0.5f)));
1536        maxTrainLengthSpinner.setEditor(new JSpinner.NumberEditor(maxTrainLengthSpinner, "###0.0"));
1537        pa4.add(maxTrainLengthSpinner);
1538        boolean unitIsMeter = InstanceManager.getDefault(DispatcherFrame.class).getUseScaleMeters(); // read from user setting
1539        maxTrainLengthSpinner.setToolTipText(Bundle.getMessage("MaxTrainLengthHint",
1540                (unitIsMeter ? Bundle.getMessage("ScaleMeters") : Bundle.getMessage("ScaleFeet")))); // won't be updated while Dispatcher is open
1541        initiatePane.add(pa4);
1542        hideAutoRunItems();   // initialize with auto run items hidden
1543    }
1544
1545   private void hideAutoRunItems() {
1546        pa1.setVisible(false);
1547        pa2.setVisible(false);
1548        pa2a.setVisible(false);
1549        pa3.setVisible(false);
1550        pa4.setVisible(false);
1551    }
1552
1553    private void showAutoRunItems() {
1554        pa1.setVisible(true);
1555        pa2.setVisible(true);
1556        pa2a.setVisible(true);
1557        pa3.setVisible(true);
1558        pa4.setVisible(true);
1559    }
1560
1561    private void autoTrainInfoToDialog(TrainInfo info) {
1562        speedFactorSpinner.setValue(info.getSpeedFactor());
1563        maxSpeedSpinner.setValue(info.getMaxSpeed());
1564        minReliableOperatingSpeedSpinner.setValue(info.getMinReliableOperatingSpeed());
1565        setComboBox(rampRateBox, info.getRampRate());
1566        trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection());
1567        runInReverseBox.setSelected(info.getRunInReverse());
1568        soundDecoderBox.setSelected(info.getSoundDecoder());
1569        maxTrainLengthSpinner.setValue(info.getMaxTrainLength());
1570        useSpeedProfileCheckBox.setSelected(info.getUseSpeedProfile());
1571        stopBySpeedProfileCheckBox.setSelected(info.getStopBySpeedProfile());
1572        stopBySpeedProfileAdjustSpinner.setValue(info.getStopBySpeedProfileAdjust());
1573        if (autoRunBox.isSelected()) {
1574            showAutoRunItems();
1575        } else {
1576            hideAutoRunItems();
1577        }
1578        initiateFrame.pack();
1579    }
1580
1581    private void autoRunItemsToTrainInfo(TrainInfo info) {
1582        info.setSpeedFactor((float) speedFactorSpinner.getValue());
1583        int max = Math.round((float) maxSpeedSpinner.getValue()*100.0f);
1584        int min = Math.round((float) minReliableOperatingSpeedSpinner.getValue()*100.0f);
1585        if ((max-min) < 10) {
1586            throw new IllegalArgumentException(Bundle.getMessage("Error49",
1587                    maxSpeedSpinner.getValue(), minReliableOperatingSpeedSpinner.getValue()));
1588        }
1589        info.setMaxSpeed((float) maxSpeedSpinner.getValue());
1590        info.setMinReliableOperatingSpeed((float) minReliableOperatingSpeedSpinner.getValue());
1591        info.setRampRate((String) rampRateBox.getSelectedItem());
1592        info.setRunInReverse(runInReverseBox.isSelected());
1593        info.setSoundDecoder(soundDecoderBox.isSelected());
1594        info.setMaxTrainLength((float) maxTrainLengthSpinner.getValue());
1595        // Only use speed profile values if enabled
1596        if (useSpeedProfileCheckBox.isEnabled()) {
1597            info.setUseSpeedProfile(useSpeedProfileCheckBox.isSelected());
1598            info.setStopBySpeedProfile(stopBySpeedProfileCheckBox.isSelected());
1599            info.setStopBySpeedProfileAdjust((float) stopBySpeedProfileAdjustSpinner.getValue());
1600        } else {
1601            info.setUseSpeedProfile(false);
1602            info.setStopBySpeedProfile(false);
1603            info.setStopBySpeedProfileAdjust(1.0f);
1604        }
1605    }
1606
1607   private void initializeRampCombo() {
1608        rampRateBox.removeAllItems();
1609        rampRateBox.addItem(Bundle.getMessage("RAMP_NONE"));
1610        rampRateBox.addItem(Bundle.getMessage("RAMP_FAST"));
1611        rampRateBox.addItem(Bundle.getMessage("RAMP_MEDIUM"));
1612        rampRateBox.addItem(Bundle.getMessage("RAMP_MED_SLOW"));
1613        rampRateBox.addItem(Bundle.getMessage("RAMP_SLOW"));
1614        rampRateBox.addItem(Bundle.getMessage("RAMP_SPEEDPROFILE"));
1615        // Note: the order above must correspond to the numbers in AutoActiveTrain.java
1616    }
1617
1618    /**
1619     * Sets up the RadioButtons and visability of spinner for the allocation method
1620     *
1621     * @param value 0, Allocate by Safe spots, -1, allocate as far as possible Any
1622     *            other value the number of sections to allocate
1623     */
1624    private void setAllocateMethodButtons(int value) {
1625        switch (value) {
1626            case ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS:
1627                allocateBySafeRadioButton.setSelected(true);
1628                allocateCustomSpinner.setVisible(false);
1629                break;
1630            case ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN:
1631                allocateAllTheWayRadioButton.setSelected(true);
1632                allocateCustomSpinner.setVisible(false);
1633                break;
1634            default:
1635                allocateNumberOfBlocks.setSelected(true);
1636                allocateCustomSpinner.setVisible(true);
1637                allocateCustomSpinner.setValue(value);
1638        }
1639    }
1640
1641    /*
1642     * ComboBox item.
1643     */
1644    protected static class TrainDetectionItem {
1645        private String key;
1646        private TrainDetection value;
1647        public TrainDetectionItem(String text, TrainDetection trainDetection ) {
1648            this.key = text;
1649            this.value = trainDetection;
1650        }
1651        @Override
1652        public String toString()
1653        {
1654            return key;
1655        }
1656        public String getKey()
1657        {
1658            return key;
1659        }
1660        public TrainDetection getValue()
1661        {
1662            return value;
1663        }
1664    }
1665
1666    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActivateTrainFrame.class);
1667
1668}