001package jmri.jmrit.operations.trains.gui;
002
003import java.awt.*;
004import java.util.ArrayList;
005import java.util.List;
006
007import javax.swing.*;
008
009import jmri.InstanceManager;
010import jmri.jmrit.operations.*;
011import jmri.jmrit.operations.locations.Location;
012import jmri.jmrit.operations.locations.LocationManager;
013import jmri.jmrit.operations.rollingstock.RollingStock;
014import jmri.jmrit.operations.rollingstock.cars.*;
015import jmri.jmrit.operations.rollingstock.engines.*;
016import jmri.jmrit.operations.routes.*;
017import jmri.jmrit.operations.routes.gui.RouteEditFrame;
018import jmri.jmrit.operations.setup.Control;
019import jmri.jmrit.operations.setup.Setup;
020import jmri.jmrit.operations.trains.Train;
021import jmri.jmrit.operations.trains.TrainManager;
022import jmri.jmrit.operations.trains.tools.*;
023import jmri.jmrit.operations.trains.trainbuilder.TrainCommon;
024import jmri.util.swing.JmriJOptionPane;
025
026/**
027 * Frame for user edit of a train
028 *
029 * @author Dan Boudreau Copyright (C) 2008, 2011, 2012, 2013, 2014
030 */
031public class TrainEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
032
033    TrainManager trainManager = InstanceManager.getDefault(TrainManager.class);
034    RouteManager routeManager = InstanceManager.getDefault(RouteManager.class);
035
036    public Train _train = null;
037    List<JCheckBox> typeCarCheckBoxes = new ArrayList<>();
038    List<JCheckBox> typeEngineCheckBoxes = new ArrayList<>();
039    List<JCheckBox> locationCheckBoxes = new ArrayList<>();
040    JPanel typeCarPanelCheckBoxes = new JPanel();
041    JPanel typeEnginePanelCheckBoxes = new JPanel();
042    JPanel roadAndLoadStatusPanel = new JPanel();
043    JPanel locationPanelCheckBoxes = new JPanel();
044    JScrollPane typeCarPane;
045    JScrollPane typeEnginePane;
046    JScrollPane locationsPane;
047
048    // labels
049    JLabel textRouteStatus = new JLabel();
050    JLabel textModel = new JLabel(Bundle.getMessage("Model"));
051    JLabel textRoad2 = new JLabel(Bundle.getMessage("Road"));
052    JLabel textRoad3 = new JLabel(Bundle.getMessage("Road"));
053    JLabel textEngine = new JLabel(Bundle.getMessage("Engines"));
054
055    // major buttons
056    JButton editButton = new JButton(Bundle.getMessage("ButtonEdit")); // edit route
057    JButton clearButton = new JButton(Bundle.getMessage("ClearAll"));
058    JButton setButton = new JButton(Bundle.getMessage("SelectAll"));
059    JButton resetButton = new JButton(Bundle.getMessage("ResetTrain"));
060    JButton saveTrainButton = new JButton(Bundle.getMessage("SaveTrain"));
061    JButton deleteTrainButton = new JButton(Bundle.getMessage("DeleteTrain"));
062    JButton addTrainButton = new JButton(Bundle.getMessage("AddTrain"));
063
064    // alternate buttons
065    JButton loadOptionButton = new JButton(Bundle.getMessage("AcceptAll"));
066    JButton roadOptionButton = new JButton(Bundle.getMessage("AcceptAll"));
067
068    // radio buttons
069    JRadioButton noneRadioButton = new JRadioButton(Bundle.getMessage("None"));
070    JRadioButton cabooseRadioButton = new JRadioButton(Bundle.getMessage("Caboose"));
071    JRadioButton fredRadioButton = new JRadioButton(Bundle.getMessage("FRED"));
072    ButtonGroup group = new ButtonGroup();
073
074    // text field
075    JTextField trainNameTextField = new JTextField(Control.max_len_string_train_name);
076    JTextField trainDescriptionTextField = new JTextField(30);
077
078    // text area
079    JTextArea commentTextArea = new JTextArea(2, 70);
080    JScrollPane commentScroller = new JScrollPane(commentTextArea);
081    JColorChooser commentColorChooser = new JColorChooser(Color.black);
082
083    // for padding out panel
084    JLabel space1 = new JLabel(" "); // before hour
085    JLabel space2 = new JLabel(" "); // between hour and minute
086    JLabel space3 = new JLabel(" "); // after minute
087    JLabel space4 = new JLabel(" "); // between route and edit
088    JLabel space5 = new JLabel(" "); // after edit
089
090    // combo boxes
091    JComboBox<String> hourBox = new JComboBox<>();
092    JComboBox<String> minuteBox = new JComboBox<>();
093    JComboBox<Route> routeBox = routeManager.getComboBox();
094    JComboBox<String> roadCabooseBox = new JComboBox<>();
095    JComboBox<String> roadEngineBox = new JComboBox<>();
096    JComboBox<String> modelEngineBox = InstanceManager.getDefault(EngineModels.class).getComboBox();
097    JComboBox<String> numEnginesBox = new JComboBox<>();
098
099    JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
100
101    public static final String DISPOSE = "dispose"; // NOI18N
102
103    public TrainEditFrame(Train train) {
104        super(Bundle.getMessage("TitleTrainEdit"));
105        // Set up the jtable in a Scroll Pane..
106        locationsPane = new JScrollPane(locationPanelCheckBoxes);
107        locationsPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
108        locationsPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Stops")));
109
110        typeCarPane = new JScrollPane(typeCarPanelCheckBoxes);
111        typeCarPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TypesCar")));
112        typeCarPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
113
114        typeEnginePane = new JScrollPane(typeEnginePanelCheckBoxes);
115        typeEnginePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
116        typeEnginePane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TypesEngine")));
117
118        _train = train;
119
120        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
121
122        // Set up the panels
123        JPanel p = new JPanel();
124        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
125        JScrollPane pPane = new JScrollPane(p);
126        pPane.setMinimumSize(new Dimension(300, 5 * trainNameTextField.getPreferredSize().height));
127        pPane.setBorder(BorderFactory.createTitledBorder(""));
128
129        // Layout the panel by rows
130        // row 1
131        JPanel p1 = new JPanel();
132        p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
133        // row 1a
134        JPanel pName = new JPanel();
135        pName.setLayout(new GridBagLayout());
136        pName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Name")));
137        addItem(pName, trainNameTextField, 0, 0);
138        // row 1b
139        JPanel pDesc = new JPanel();
140        pDesc.setLayout(new GridBagLayout());
141        pDesc.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Description")));
142        trainDescriptionTextField.setToolTipText(Bundle.getMessage("TipTrainDescription"));
143        addItem(pDesc, trainDescriptionTextField, 0, 0);
144
145        p1.add(pName);
146        p1.add(pDesc);
147
148        // row 2
149        JPanel p2 = new JPanel();
150        p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
151        // row 2a
152        JPanel pdt = new JPanel();
153        pdt.setLayout(new GridBagLayout());
154        pdt.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("DepartTime")));
155
156        // build hour and minute menus
157        hourBox.setPrototypeDisplayValue("0000"); // needed for font size 9
158        minuteBox.setPrototypeDisplayValue("0000");
159        for (int i = 0; i < 24; i++) {
160            if (i < 10) {
161                hourBox.addItem("0" + Integer.toString(i));
162            } else {
163                hourBox.addItem(Integer.toString(i));
164            }
165        }
166        for (int i = 0; i < 60; i += 1) {
167            if (i < 10) {
168                minuteBox.addItem("0" + Integer.toString(i));
169            } else {
170                minuteBox.addItem(Integer.toString(i));
171            }
172        }
173
174        addItem(pdt, space1, 0, 5);
175        addItem(pdt, hourBox, 1, 5);
176        addItem(pdt, space2, 2, 5);
177        addItem(pdt, minuteBox, 3, 5);
178        addItem(pdt, space3, 4, 5);
179        // row 2b
180        // BUG! routeBox needs its own panel when resizing frame!
181        JPanel pr = new JPanel();
182        pr.setLayout(new GridBagLayout());
183        pr.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Route")));
184        addItem(pr, routeBox, 0, 5);
185        addItem(pr, space4, 1, 5);
186        addItem(pr, editButton, 2, 5);
187        addItem(pr, space5, 3, 5);
188        addItem(pr, textRouteStatus, 4, 5);
189
190        p2.add(pdt);
191        p2.add(pr);
192
193        p.add(p1);
194        p.add(p2);
195
196        // row 5
197        locationPanelCheckBoxes.setLayout(new GridBagLayout());
198
199        // row 6
200        typeCarPanelCheckBoxes.setLayout(new GridBagLayout());
201
202        // row 8
203        typeEnginePanelCheckBoxes.setLayout(new GridBagLayout());
204
205        // status panel for roads and loads
206        roadAndLoadStatusPanel.setLayout(new BoxLayout(roadAndLoadStatusPanel, BoxLayout.X_AXIS));
207        JPanel pRoadOption = new JPanel();
208        pRoadOption.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RoadOption")));
209        pRoadOption.add(roadOptionButton);
210        roadOptionButton.addActionListener(new TrainRoadOptionsAction(this));
211
212        JPanel pLoadOption = new JPanel();
213        pLoadOption.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LoadOption")));
214        pLoadOption.add(loadOptionButton);
215        loadOptionButton.addActionListener(new TrainLoadOptionsAction(this));
216
217        roadAndLoadStatusPanel.add(pRoadOption);
218        roadAndLoadStatusPanel.add(pLoadOption);
219        roadAndLoadStatusPanel.setVisible(false); // don't show unless there's a restriction
220
221        // row 10
222        JPanel trainReq = new JPanel();
223        trainReq.setLayout(new GridBagLayout());
224        trainReq.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainRequires")));
225
226        for (int i = 0; i < Setup.getMaxNumberEngines() + 1; i++) {
227            numEnginesBox.addItem(Integer.toString(i));
228        }
229        numEnginesBox.addItem(Train.AUTO);
230        numEnginesBox.setMinimumSize(new Dimension(100, 20));
231        numEnginesBox.setToolTipText(Bundle.getMessage("TipNumberOfLocos"));
232        addItem(trainReq, textEngine, 1, 1);
233        addItem(trainReq, numEnginesBox, 2, 1);
234        addItem(trainReq, textModel, 3, 1);
235        modelEngineBox.insertItemAt(NONE, 0);
236        modelEngineBox.setSelectedIndex(0);
237        modelEngineBox.setMinimumSize(new Dimension(120, 20));
238        modelEngineBox.setToolTipText(Bundle.getMessage("ModelEngineTip"));
239        addItem(trainReq, modelEngineBox, 4, 1);
240        addItem(trainReq, textRoad2, 5, 1);
241        roadEngineBox.insertItemAt(NONE, 0);
242        roadEngineBox.setSelectedIndex(0);
243        roadEngineBox.setMinimumSize(new Dimension(120, 20));
244        roadEngineBox.setToolTipText(Bundle.getMessage("RoadEngineTip"));
245        addItem(trainReq, roadEngineBox, 6, 1);
246
247        JPanel trainLastCar = new JPanel();
248        trainLastCar.setLayout(new GridBagLayout());
249        trainLastCar.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainLastCar")));
250
251        addItem(trainLastCar, noneRadioButton, 2, 2);
252        noneRadioButton.setToolTipText(Bundle.getMessage("TipNoCabooseOrFRED"));
253        addItem(trainLastCar, fredRadioButton, 3, 2);
254        fredRadioButton.setToolTipText(Bundle.getMessage("TipFRED"));
255        addItem(trainLastCar, cabooseRadioButton, 4, 2);
256        cabooseRadioButton.setToolTipText(Bundle.getMessage("TipCaboose"));
257        addItem(trainLastCar, textRoad3, 5, 2);
258        roadCabooseBox.setMinimumSize(new Dimension(120, 20));
259        roadCabooseBox.setToolTipText(Bundle.getMessage("RoadCabooseTip"));
260        addItem(trainLastCar, roadCabooseBox, 6, 2);
261        group.add(noneRadioButton);
262        group.add(cabooseRadioButton);
263        group.add(fredRadioButton);
264        noneRadioButton.setSelected(true);
265
266        // row 13 comment
267        JPanel pC = new JPanel();
268        pC.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Comment")));
269        pC.setLayout(new GridBagLayout());
270        addItem(pC, commentScroller, 1, 0);
271        if (_train != null) {
272            addItem(pC, OperationsPanel.getColorChooserPanel(_train.getCommentWithColor(), commentColorChooser), 2, 0);
273        } else {
274            addItem(pC, OperationsPanel.getColorChooserPanel("", commentColorChooser), 2, 0);
275        }
276
277        // adjust text area width based on window size less color chooser
278        Dimension d = new Dimension(getPreferredSize().width - 100, getPreferredSize().height);
279        adjustTextAreaColumnWidth(commentScroller, commentTextArea, d);
280
281        // row 15 buttons
282        JPanel pB = new JPanel();
283        pB.setLayout(new GridBagLayout());
284        addItem(pB, deleteTrainButton, 0, 0);
285        addItem(pB, resetButton, 1, 0);
286        addItem(pB, addTrainButton, 2, 0);
287        addItem(pB, saveTrainButton, 3, 0);
288
289        getContentPane().add(pPane);
290        getContentPane().add(locationsPane);
291        getContentPane().add(typeCarPane);
292        getContentPane().add(typeEnginePane);
293        getContentPane().add(roadAndLoadStatusPanel);
294        getContentPane().add(trainReq);
295        getContentPane().add(trainLastCar);
296        getContentPane().add(pC);
297        getContentPane().add(pB);
298
299        // setup buttons
300        addButtonAction(editButton);
301        addButtonAction(setButton);
302        addButtonAction(clearButton);
303        addButtonAction(resetButton);
304        addButtonAction(deleteTrainButton);
305        addButtonAction(addTrainButton);
306        addButtonAction(saveTrainButton);
307
308        addRadioButtonAction(noneRadioButton);
309        addRadioButtonAction(cabooseRadioButton);
310        addRadioButtonAction(fredRadioButton);
311
312        // tool tips
313        resetButton.setToolTipText(Bundle.getMessage("TipTrainReset"));
314
315        // build menu
316        JMenuBar menuBar = new JMenuBar();
317        menuBar.add(toolMenu);
318        loadToolMenu(toolMenu);
319        setJMenuBar(menuBar);
320        addHelpMenu("package.jmri.jmrit.operations.Operations_TrainEdit", true); // NOI18N
321
322        if (_train != null) {
323            trainNameTextField.setText(_train.getName());
324            trainDescriptionTextField.setText(_train.getRawDescription());
325            routeBox.setSelectedItem(_train.getRoute());
326            modelEngineBox.setSelectedItem(_train.getEngineModel());
327            commentTextArea.setText(TrainCommon.getTextColorString(_train.getCommentWithColor()));
328            cabooseRadioButton.setSelected(_train.isCabooseNeeded());
329            fredRadioButton.setSelected(_train.isFredNeeded());
330            updateDepartureTime();
331            enableButtons(true);
332            // listen for train changes
333            _train.addPropertyChangeListener(this);
334
335            Route route = _train.getRoute();
336            if (route != null) {
337                if (_train.getTrainDepartsRouteLocation() != null &&
338                        _train.getTrainDepartsRouteLocation().getLocation() != null &&
339                        !_train.getTrainDepartsRouteLocation().getLocation().isStaging())
340                    numEnginesBox.addItem(Train.AUTO_HPT);
341            }
342            numEnginesBox.setSelectedItem(_train.getNumberEngines());
343        } else {
344            setTitle(Bundle.getMessage("TitleTrainAdd"));
345            enableButtons(false);
346        }
347
348        modelEngineBox.setEnabled(!numEnginesBox.getSelectedItem().equals("0"));
349        roadEngineBox.setEnabled(!numEnginesBox.getSelectedItem().equals("0"));
350
351        // load route location checkboxes
352        updateLocationCheckboxes();
353        updateCarTypeCheckboxes();
354        updateEngineTypeCheckboxes();
355        updateRoadAndLoadStatus();
356        updateCabooseRoadComboBox();
357        updateEngineRoadComboBox();
358
359        // setup combobox
360        addComboBoxAction(numEnginesBox);
361        addComboBoxAction(routeBox);
362        addComboBoxAction(modelEngineBox);
363
364        // get notified if combo box gets modified
365        routeManager.addPropertyChangeListener(this);
366        // get notified if car types or roads gets modified
367        InstanceManager.getDefault(CarTypes.class).addPropertyChangeListener(this);
368        InstanceManager.getDefault(CarRoads.class).addPropertyChangeListener(this);
369        InstanceManager.getDefault(EngineTypes.class).addPropertyChangeListener(this);
370        InstanceManager.getDefault(EngineModels.class).addPropertyChangeListener(this);
371        InstanceManager.getDefault(LocationManager.class).addPropertyChangeListener(this);
372
373        initMinimumSize(new Dimension(Control.panelWidth600, Control.panelHeight600));
374    }
375
376    private void loadToolMenu(JMenu toolMenu) {
377        toolMenu.removeAll();
378        // first 4 menu items will also close when the edit train window closes
379        toolMenu.add(new TrainEditBuildOptionsAction(this));
380        toolMenu.add(new TrainLoadOptionsAction(this));
381        toolMenu.add(new TrainRoadOptionsAction(this));
382        toolMenu.add(new TrainManifestOptionAction(this));
383        toolMenu.addSeparator();
384        toolMenu.add(new TrainCopyAction(_train));
385        toolMenu.addSeparator();
386        // scripts window closes when the edit train window closes
387        toolMenu.add(new TrainScriptAction(this));
388        toolMenu.addSeparator();
389        toolMenu.add(new TrainConductorAction(_train));
390        toolMenu.addSeparator();
391        toolMenu.add(new TrainByCarTypeAction(_train));
392        toolMenu.addSeparator();
393        toolMenu.add(new PrintTrainAction(false, _train));
394        toolMenu.add(new PrintTrainAction(true, _train));
395        toolMenu.add(new PrintTrainManifestAction(false, _train));
396        toolMenu.add(new PrintTrainManifestAction(true, _train));
397        toolMenu.add(new PrintShowCarsInTrainRouteAction(false, _train));
398        toolMenu.add(new PrintShowCarsInTrainRouteAction(true, _train));
399        toolMenu.add(new PrintTrainBuildReportAction(false, _train));
400        toolMenu.add(new PrintTrainBuildReportAction(true, _train));
401        toolMenu.add(new PrintSavedTrainManifestAction(false, _train));
402        toolMenu.add(new PrintSavedTrainManifestAction(true, _train));
403        toolMenu.add(new PrintSavedBuildReportAction(false, _train));
404        toolMenu.add(new PrintSavedBuildReportAction(true, _train));
405    }
406
407    // Save, Delete, Add, Edit, Reset, Set, Clear
408    @Override
409    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
410        Train train = trainManager.getTrainByName(trainNameTextField.getText().trim());
411        if (ae.getSource() == saveTrainButton) {
412            log.debug("train save button activated");
413            if (_train == null && train == null) {
414                saveNewTrain(); // this can't happen, Save button is disabled
415            } else {
416                if (train != null && train != _train) {
417                    reportTrainExists(Bundle.getMessage("save"));
418                    return;
419                }
420                // check to see if user supplied a route
421                if (!checkRoute() || !saveTrain()) {
422                    return;
423                }
424            }
425            if (Setup.isCloseWindowOnSaveEnabled()) {
426                dispose();
427            }
428        }
429        if (ae.getSource() == deleteTrainButton) {
430            log.debug("train delete button activated");
431            if (train == null) {
432                return;
433            }
434            if (!_train.reset()) {
435                JmriJOptionPane.showMessageDialog(this,
436                        Bundle.getMessage("TrainIsInRoute",
437                                train.getTrainTerminatesName()),
438                        Bundle.getMessage("CanNotDeleteTrain"), JmriJOptionPane.ERROR_MESSAGE);
439                return;
440            }
441            if (JmriJOptionPane.showConfirmDialog(this,
442                    Bundle.getMessage("deleteMsg", train.getName()),
443                    Bundle.getMessage("deleteTrain"), JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) {
444                return;
445            }
446            routeBox.setSelectedItem(null);
447            trainManager.deregister(train);
448            for (Frame frame : children) {
449                frame.dispose();
450            }
451            _train = null;
452            enableButtons(false);
453            // save train file
454            OperationsXml.save();
455        }
456        if (ae.getSource() == addTrainButton) {
457            if (train != null) {
458                reportTrainExists(Bundle.getMessage("add"));
459                return;
460            }
461            saveNewTrain();
462        }
463        if (ae.getSource() == editButton) {
464            editAddRoute();
465        }
466        if (ae.getSource() == setButton) {
467            selectCheckboxes(true);
468        }
469        if (ae.getSource() == clearButton) {
470            selectCheckboxes(false);
471        }
472        if (ae.getSource() == resetButton) {
473            if (_train != null) {
474                if (_train.checkDepartureTrack()) {
475                    int results = JmriJOptionPane.showConfirmDialog(null,
476                            Bundle.getMessage("StagingTrackUsed",
477                                    _train.getDepartureTrack().getName()),
478                            Bundle.getMessage("ShouldNotResetTrain"), JmriJOptionPane.OK_CANCEL_OPTION);
479                    if (results == JmriJOptionPane.OK_CANCEL_OPTION) {
480                        return;
481                    }
482                }
483                if (!_train.reset()) {
484                    JmriJOptionPane.showMessageDialog(this,
485                            Bundle.getMessage("TrainIsInRoute",
486                                    _train.getTrainTerminatesName()),
487                            Bundle.getMessage("CanNotResetTrain"), JmriJOptionPane.ERROR_MESSAGE);
488                }
489            }
490        }
491    }
492
493    @Override
494    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
495        log.debug("radio button activated");
496        if (_train != null) {
497            if (ae.getSource() == noneRadioButton ||
498                    ae.getSource() == cabooseRadioButton ||
499                    ae.getSource() == fredRadioButton) {
500                updateCabooseRoadComboBox();
501            }
502        }
503    }
504
505    private void saveNewTrain() {
506        if (!checkName(Bundle.getMessage("add"))) {
507            return;
508        }
509        Train train = trainManager.newTrain(trainNameTextField.getText());
510        _train = train;
511        _train.addPropertyChangeListener(this);
512
513        // update check boxes
514        updateCarTypeCheckboxes();
515        updateEngineTypeCheckboxes();
516        // enable check boxes and buttons
517        enableButtons(true);
518        saveTrain();
519        loadToolMenu(toolMenu);
520    }
521
522    private boolean saveTrain() {
523        if (!checkName(Bundle.getMessage("save"))) {
524            return false;
525        }
526        if (!checkModel() || !checkEngineRoad() || !checkCabooseRoad()) {
527            return false;
528        }
529        if (!_train.getName().equals(trainNameTextField.getText().trim()) ||
530                !_train.getRawDescription().equals(trainDescriptionTextField.getText()) ||
531                !_train.getCommentWithColor().equals(
532                        TrainCommon.formatColorString(commentTextArea.getText(), commentColorChooser.getColor()))) {
533            _train.setModified(true);
534        }
535        _train.setDepartureTime(hourBox.getSelectedItem().toString(), minuteBox.getSelectedItem().toString());
536        _train.setNumberEngines((String) numEnginesBox.getSelectedItem());
537        if (_train.getNumberEngines().equals("0")) {
538            modelEngineBox.setSelectedIndex(0);
539            roadEngineBox.setSelectedIndex(0);
540        }
541        _train.setEngineRoad((String) roadEngineBox.getSelectedItem());
542        _train.setEngineModel((String) modelEngineBox.getSelectedItem());
543        if (cabooseRadioButton.isSelected()) {
544            _train.setRequirements(Train.CABOOSE);
545        }
546        if (fredRadioButton.isSelected()) {
547            _train.setRequirements(Train.FRED);
548        }
549        if (noneRadioButton.isSelected()) {
550            _train.setRequirements(Train.NO_CABOOSE_OR_FRED);
551        }
552        _train.setCabooseRoad((String) roadCabooseBox.getSelectedItem());
553        _train.setName(trainNameTextField.getText().trim());
554        _train.setDescription(trainDescriptionTextField.getText());
555        _train.setComment(TrainCommon.formatColorString(commentTextArea.getText(), commentColorChooser.getColor()));
556        // save train file
557        OperationsXml.save();
558        return true;
559    }
560
561    /**
562     *
563     * @return true if name isn't too long and is at least one character
564     */
565    private boolean checkName(String s) {
566        String trainName = trainNameTextField.getText().trim();
567        if (trainName.isEmpty()) {
568            log.debug("Must enter a train name");
569            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MustEnterName"),
570                    Bundle.getMessage("CanNot", s), JmriJOptionPane.ERROR_MESSAGE);
571            return false;
572        }
573        if (trainName.length() > Control.max_len_string_train_name) {
574            JmriJOptionPane.showMessageDialog(this,
575                    Bundle.getMessage("TrainNameLess",
576                            Control.max_len_string_train_name + 1),
577                    Bundle.getMessage("CanNot", s), JmriJOptionPane.ERROR_MESSAGE);
578            return false;
579        }
580        if (!OperationsXml.checkFileName(trainName)) { // NOI18N
581            log.error("Train name must not contain reserved characters");
582            JmriJOptionPane.showMessageDialog(this,
583                    Bundle.getMessage("NameResChar") + NEW_LINE + Bundle.getMessage("ReservedChar"),
584                    Bundle.getMessage("CanNot", s), JmriJOptionPane.ERROR_MESSAGE);
585            return false;
586        }
587
588        return true;
589    }
590
591    private boolean checkModel() {
592        String model = (String) modelEngineBox.getSelectedItem();
593        if (numEnginesBox.getSelectedItem().equals("0") || model.equals(NONE)) {
594            return true;
595        }
596        String type = InstanceManager.getDefault(EngineModels.class).getModelType(model);
597        if (!_train.isTypeNameAccepted(type)) {
598            JmriJOptionPane.showMessageDialog(this,
599                    Bundle.getMessage("TrainModelService", model, type),
600                    Bundle.getMessage("CanNot", Bundle.getMessage("save")),
601                    JmriJOptionPane.ERROR_MESSAGE);
602            return false;
603        }
604        if (roadEngineBox.getItemCount() == 1) {
605            log.debug("No locos available that match the model selected!");
606            JmriJOptionPane.showMessageDialog(this,
607                    Bundle.getMessage("NoLocosModel", model),
608                    Bundle.getMessage("TrainWillNotBuild", _train.getName()),
609                    JmriJOptionPane.WARNING_MESSAGE);
610        }
611        return true;
612    }
613
614    private boolean checkEngineRoad() {
615        String road = (String) roadEngineBox.getSelectedItem();
616        if (numEnginesBox.getSelectedItem().equals("0") || road.equals(NONE)) {
617            return true;
618        }
619        if (!road.equals(NONE) && !_train.isLocoRoadNameAccepted(road)) {
620            JmriJOptionPane.showMessageDialog(this,
621                    Bundle.getMessage("TrainNotThisRoad", _train.getName(), road),
622                    Bundle.getMessage("TrainWillNotBuild", _train.getName()),
623                    JmriJOptionPane.WARNING_MESSAGE);
624            return false;
625        }
626        for (RollingStock rs : InstanceManager.getDefault(EngineManager.class).getList()) {
627            if (!_train.isTypeNameAccepted(rs.getTypeName())) {
628                continue;
629            }
630            if (rs.getRoadName().equals(road)) {
631                return true;
632            }
633        }
634        JmriJOptionPane.showMessageDialog(this,
635                Bundle.getMessage("NoLocoRoad", road),
636                Bundle.getMessage("TrainWillNotBuild", _train.getName()),
637                JmriJOptionPane.WARNING_MESSAGE);
638        return false; // couldn't find a loco with the selected road
639    }
640
641    private boolean checkCabooseRoad() {
642        String road = (String) roadCabooseBox.getSelectedItem();
643        if (!road.equals(NONE) && cabooseRadioButton.isSelected() && !_train.isCabooseRoadNameAccepted(road)) {
644            JmriJOptionPane.showMessageDialog(this,
645                    Bundle.getMessage("TrainNotCabooseRoad", _train.getName(), road),
646                    Bundle.getMessage("TrainWillNotBuild", _train.getName()),
647                    JmriJOptionPane.WARNING_MESSAGE);
648            return false;
649        }
650        return true;
651    }
652
653    private boolean checkRoute() {
654        if (_train.getRoute() == null) {
655            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("TrainNeedsRoute"), Bundle.getMessage("TrainNoRoute"),
656                    JmriJOptionPane.WARNING_MESSAGE);
657            return false;
658        }
659        return true;
660
661    }
662
663    private void reportTrainExists(String s) {
664        log.debug("Can not {}, train already exists", s);
665        JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("TrainNameExists"),
666                Bundle.getMessage("CanNot", s), JmriJOptionPane.ERROR_MESSAGE);
667    }
668
669    private void enableButtons(boolean enabled) {
670        toolMenu.setEnabled(enabled);
671        editButton.setEnabled(enabled);
672        routeBox.setEnabled(enabled && _train != null && !_train.isBuilt());
673        clearButton.setEnabled(enabled);
674        resetButton.setEnabled(enabled);
675        setButton.setEnabled(enabled);
676        saveTrainButton.setEnabled(enabled);
677        deleteTrainButton.setEnabled(enabled);
678        numEnginesBox.setEnabled(enabled);
679        enableCheckboxes(enabled);
680        noneRadioButton.setEnabled(enabled);
681        fredRadioButton.setEnabled(enabled);
682        cabooseRadioButton.setEnabled(enabled);
683        roadOptionButton.setEnabled(enabled);
684        loadOptionButton.setEnabled(enabled);
685        // the inverse!
686        addTrainButton.setEnabled(!enabled);
687    }
688
689    private void selectCheckboxes(boolean enable) {
690        for (int i = 0; i < typeCarCheckBoxes.size(); i++) {
691            JCheckBox checkBox = typeCarCheckBoxes.get(i);
692            checkBox.setSelected(enable);
693            if (_train != null) {
694                _train.removePropertyChangeListener(this);
695                if (enable) {
696                    _train.addTypeName(checkBox.getText());
697                } else {
698                    _train.deleteTypeName(checkBox.getText());
699                }
700                _train.addPropertyChangeListener(this);
701            }
702        }
703    }
704
705    @Override
706    public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
707        if (_train == null) {
708            return;
709        }
710        if (ae.getSource() == numEnginesBox) {
711            modelEngineBox.setEnabled(!numEnginesBox.getSelectedItem().equals("0"));
712            roadEngineBox.setEnabled(!numEnginesBox.getSelectedItem().equals("0"));
713        }
714        if (ae.getSource() == modelEngineBox) {
715            updateEngineRoadComboBox();
716        }
717        if (ae.getSource() == routeBox) {
718            if (routeBox.isEnabled()) {
719                Route route = _train.getRoute();
720                if (route != null) {
721                    route.removePropertyChangeListener(this);
722                }
723                Object selected = routeBox.getSelectedItem();
724                if (selected != null) {
725                    route = (Route) selected;
726                    _train.setRoute(route);
727                    route.addPropertyChangeListener(this);
728                } else {
729                    _train.setRoute(null);
730                }
731                updateLocationCheckboxes();
732                updateDepartureTime();
733                pack();
734                repaint();
735            }
736        }
737    }
738
739    private void enableCheckboxes(boolean enable) {
740        for (int i = 0; i < typeCarCheckBoxes.size(); i++) {
741            typeCarCheckBoxes.get(i).setEnabled(enable);
742        }
743        for (int i = 0; i < typeEngineCheckBoxes.size(); i++) {
744            typeEngineCheckBoxes.get(i).setEnabled(enable);
745        }
746    }
747
748    private void addLocationCheckBoxAction(JCheckBox b) {
749        b.addActionListener(new java.awt.event.ActionListener() {
750            @Override
751            public void actionPerformed(java.awt.event.ActionEvent e) {
752                locationCheckBoxActionPerformed(e);
753            }
754        });
755    }
756
757    public void locationCheckBoxActionPerformed(java.awt.event.ActionEvent ae) {
758        JCheckBox b = (JCheckBox) ae.getSource();
759        log.debug("checkbox change {}", b.getText());
760        if (_train == null) {
761            return;
762        }
763        String id = b.getName();
764        RouteLocation rl = _train.getRoute().getRouteLocationById(id);
765        if (b.isSelected()) {
766            _train.deleteTrainSkipsLocation(rl);
767        } else {
768            // check to see if skipped location is staging
769            if (_train.getRoute().getRouteLocationById(id).getLocation().isStaging()) {
770                int result = JmriJOptionPane.showConfirmDialog(this,
771                        Bundle.getMessage("TrainRouteStaging",
772                                _train.getName(), _train.getRoute().getRouteLocationById(id).getName()),
773                        Bundle.getMessage("TrainRouteNotStaging"), JmriJOptionPane.OK_CANCEL_OPTION);
774                if (result != JmriJOptionPane.OK_OPTION ) {
775                    b.setSelected(true);
776                    return; // don't skip staging
777                }
778            }
779            _train.addTrainSkipsLocation(rl);
780        }
781    }
782
783    private void updateRouteComboBox() {
784        routeBox.setEnabled(false);
785        routeManager.updateComboBox(routeBox);
786        if (_train != null) {
787            routeBox.setSelectedItem(_train.getRoute());
788        }
789        routeBox.setEnabled(true);
790    }
791
792    private void updateCarTypeCheckboxes() {
793        typeCarCheckBoxes.clear();
794        typeCarPanelCheckBoxes.removeAll();
795        loadCarTypes();
796        enableCheckboxes(_train != null);
797        typeCarPanelCheckBoxes.revalidate();
798        repaint();
799    }
800
801    private void loadCarTypes() {
802        int numberOfCheckboxes = getNumberOfCheckboxesPerLine(); // number per line
803        int x = 0;
804        int y = 1; // vertical position in panel
805        for (String type : InstanceManager.getDefault(CarTypes.class).getNames()) {
806            JCheckBox checkBox = new javax.swing.JCheckBox();
807            typeCarCheckBoxes.add(checkBox);
808            checkBox.setText(type);
809            addTypeCheckBoxAction(checkBox);
810            addItemLeft(typeCarPanelCheckBoxes, checkBox, x++, y);
811            if (_train != null && _train.isTypeNameAccepted(type)) {
812                checkBox.setSelected(true);
813            }
814            if (x > numberOfCheckboxes) {
815                y++;
816                x = 0;
817            }
818        }
819
820        JPanel p = new JPanel();
821        p.add(clearButton);
822        p.add(setButton);
823        GridBagConstraints gc = new GridBagConstraints();
824        gc.gridwidth = getNumberOfCheckboxesPerLine() + 1;
825        gc.gridy = ++y;
826        typeCarPanelCheckBoxes.add(p, gc);
827
828    }
829
830    private void updateEngineTypeCheckboxes() {
831        typeEngineCheckBoxes.clear();
832        typeEnginePanelCheckBoxes.removeAll();
833        loadEngineTypes();
834        enableCheckboxes(_train != null);
835        typeEnginePanelCheckBoxes.revalidate();
836        repaint();
837    }
838
839    private void loadEngineTypes() {
840        int numberOfCheckboxes = getNumberOfCheckboxesPerLine(); // number per line
841        int x = 0;
842        int y = 1;
843        for (String type : InstanceManager.getDefault(EngineTypes.class).getNames()) {
844            JCheckBox checkBox = new javax.swing.JCheckBox();
845            typeEngineCheckBoxes.add(checkBox);
846            checkBox.setText(type);
847            addTypeCheckBoxAction(checkBox);
848            addItemLeft(typeEnginePanelCheckBoxes, checkBox, x++, y);
849            if (_train != null && _train.isTypeNameAccepted(type)) {
850                checkBox.setSelected(true);
851            }
852            if (x > numberOfCheckboxes) {
853                y++;
854                x = 0;
855            }
856        }
857    }
858
859    private void updateRoadComboBoxes() {
860        updateCabooseRoadComboBox();
861        updateEngineRoadComboBox();
862    }
863
864    // update caboose road box based on radio selection
865    private void updateCabooseRoadComboBox() {
866        roadCabooseBox.removeAllItems();
867        roadCabooseBox.addItem(NONE);
868        if (noneRadioButton.isSelected()) {
869            roadCabooseBox.setEnabled(false);
870            return;
871        }
872        roadCabooseBox.setEnabled(true);
873        List<String> roads;
874        if (cabooseRadioButton.isSelected()) {
875            roads = InstanceManager.getDefault(CarManager.class).getCabooseRoadNames();
876        } else {
877            roads = InstanceManager.getDefault(CarManager.class).getFredRoadNames();
878        }
879        for (String road : roads) {
880            roadCabooseBox.addItem(road);
881        }
882        if (_train != null) {
883            roadCabooseBox.setSelectedItem(_train.getCabooseRoad());
884        }
885        OperationsPanel.padComboBox(roadCabooseBox);
886    }
887
888    private void updateEngineRoadComboBox() {
889        String engineModel = (String) modelEngineBox.getSelectedItem();
890        if (engineModel == null) {
891            return;
892        }
893        InstanceManager.getDefault(EngineManager.class).updateEngineRoadComboBox(engineModel, roadEngineBox);
894        if (_train != null) {
895            roadEngineBox.setSelectedItem(_train.getEngineRoad());
896        }
897    }
898
899    private void addTypeCheckBoxAction(JCheckBox b) {
900        b.addActionListener(new java.awt.event.ActionListener() {
901            @Override
902            public void actionPerformed(java.awt.event.ActionEvent e) {
903                typeCheckBoxActionPerformed(e);
904            }
905        });
906    }
907
908    public void typeCheckBoxActionPerformed(java.awt.event.ActionEvent ae) {
909        JCheckBox b = (JCheckBox) ae.getSource();
910        log.debug("checkbox change {}", b.getText());
911        if (_train == null) {
912            return;
913        }
914        if (b.isSelected()) {
915            _train.addTypeName(b.getText());
916        } else {
917            _train.deleteTypeName(b.getText());
918        }
919    }
920
921    // the train's route shown as locations with checkboxes
922    private void updateLocationCheckboxes() {
923        updateRouteStatus();
924        locationCheckBoxes.clear();
925        locationPanelCheckBoxes.removeAll();
926        int y = 0; // vertical position in panel
927        Route route = null;
928        if (_train != null) {
929            route = _train.getRoute();
930        }
931        if (route != null) {
932            List<RouteLocation> routeList = route.getLocationsBySequenceList();
933            for (RouteLocation rl : routeList) {
934                JCheckBox checkBox = new javax.swing.JCheckBox();
935                locationCheckBoxes.add(checkBox);
936                checkBox.setText(rl.toString());
937                checkBox.setName(rl.getId());
938                addItemLeft(locationPanelCheckBoxes, checkBox, 0, y++);
939                Location loc = InstanceManager.getDefault(LocationManager.class).getLocationByName(rl.getName());
940                // does the location exist?
941                if (loc != null) {
942                    // need to listen for name and direction changes
943                    loc.removePropertyChangeListener(this);
944                    loc.addPropertyChangeListener(this);
945                    boolean services = false;
946                    // does train direction service location?
947                    if ((rl.getTrainDirection() & loc.getTrainDirections()) != 0) {
948                        services = true;
949                    } // train must service last location or single location
950                    else if (_train.isLocalSwitcher() || rl == _train.getTrainTerminatesRouteLocation()) {
951                        services = true;
952                    }
953                    // check can drop and pick up, and moves > 0
954                    if (services &&
955                            (rl.isDropAllowed() || rl.isPickUpAllowed() || rl.isLocalMovesAllowed()) &&
956                            rl.getMaxCarMoves() > 0) {
957                        checkBox.setSelected(!_train.isLocationSkipped(rl));
958                    } else {
959                        checkBox.setEnabled(false);
960                    }
961                    addLocationCheckBoxAction(checkBox);
962                } else {
963                    checkBox.setEnabled(false);
964                }
965            }
966        }
967        locationPanelCheckBoxes.revalidate();
968    }
969
970    private void updateRouteStatus() {
971        Route route = null;
972        textRouteStatus.setText(NONE); // clear out previous status
973        if (_train != null) {
974            route = _train.getRoute();
975        }
976        if (route != null) {
977            if (!route.getStatus().equals(Route.OKAY)) {
978                textRouteStatus.setText(route.getStatus());
979                textRouteStatus.setForeground(Color.RED);
980            }
981        }
982    }
983
984    RouteEditFrame ref;
985
986    private void editAddRoute() {
987        log.debug("Edit/add route");
988        if (ref != null) {
989            ref.dispose();
990        }
991        ref = new RouteEditFrame();
992        setChildFrame(ref);
993        Route route = null;
994        Object selected = routeBox.getSelectedItem();
995        if (selected != null) {
996            route = (Route) selected;
997        }
998        // warn user if train is built that they shouldn't edit the train's route
999        if (route != null && route.getStatus().equals(Route.TRAIN_BUILT)) {
1000            // list the built trains for this route
1001            StringBuffer buf = new StringBuffer(Bundle.getMessage("DoNotModifyRoute"));
1002            for (Train train : InstanceManager.getDefault(TrainManager.class).getTrainsByIdList()) {
1003                if (train.getRoute() == route && train.isBuilt()) {
1004                    buf.append(NEW_LINE +
1005                            Bundle.getMessage("TrainIsBuilt",
1006                                    train.getName(), route.getName()));
1007                }
1008            }
1009            JmriJOptionPane.showMessageDialog(this, buf.toString(), Bundle.getMessage("BuiltTrain"),
1010                    JmriJOptionPane.WARNING_MESSAGE);
1011        }
1012        ref.initComponents(route, _train);
1013    }
1014
1015    private void updateDepartureTime() {
1016        hourBox.setSelectedItem(_train.getDepartureTimeHour());
1017        minuteBox.setSelectedItem(_train.getDepartureTimeMinute());
1018        // check to see if route has a departure time from the 1st location
1019        RouteLocation rl = _train.getTrainDepartsRouteLocation();
1020        if (rl != null && !rl.getDepartureTime().equals(NONE)) {
1021            hourBox.setEnabled(false);
1022            minuteBox.setEnabled(false);
1023        } else {
1024            hourBox.setEnabled(!_train.isBuilt());
1025            minuteBox.setEnabled(!_train.isBuilt());
1026        }
1027    }
1028
1029    private void updateRoadAndLoadStatus() {
1030        if (_train != null) {
1031            // road options
1032            if (_train.getCarRoadOption().equals(Train.INCLUDE_ROADS)) {
1033                roadOptionButton.setText(Bundle.getMessage(
1034                        "AcceptOnly") + " " + _train.getCarRoadNames().length + " " + Bundle.getMessage("RoadsCar"));
1035            } else if (_train.getCarRoadOption().equals(Train.EXCLUDE_ROADS)) {
1036                roadOptionButton.setText(Bundle.getMessage(
1037                        "Exclude") + " " + _train.getCarRoadNames().length + " " + Bundle.getMessage("RoadsCar"));
1038            } else if (_train.getCabooseRoadOption().equals(Train.INCLUDE_ROADS)) {
1039                roadOptionButton.setText(Bundle.getMessage(
1040                        "AcceptOnly") +
1041                        " " +
1042                        _train.getCabooseRoadNames().length +
1043                        " " +
1044                        Bundle.getMessage("RoadsCaboose"));
1045            } else if (_train.getCabooseRoadOption().equals(Train.EXCLUDE_ROADS)) {
1046                roadOptionButton.setText(Bundle.getMessage(
1047                        "Exclude") +
1048                        " " +
1049                        _train.getCabooseRoadNames().length +
1050                        " " +
1051                        Bundle.getMessage("RoadsCaboose"));
1052            } else if (_train.getLocoRoadOption().equals(Train.INCLUDE_ROADS)) {
1053                roadOptionButton.setText(Bundle.getMessage(
1054                        "AcceptOnly") + " " + _train.getLocoRoadNames().length + " " + Bundle.getMessage("RoadsLoco"));
1055            } else if (_train.getLocoRoadOption().equals(Train.EXCLUDE_ROADS)) {
1056                roadOptionButton.setText(Bundle.getMessage(
1057                        "Exclude") + " " + _train.getLocoRoadNames().length + " " + Bundle.getMessage("RoadsLoco"));
1058            } else {
1059                roadOptionButton.setText(Bundle.getMessage("AcceptAll"));
1060            }
1061            // load options
1062            if (_train.getLoadOption().equals(Train.ALL_LOADS)) {
1063                loadOptionButton.setText(Bundle.getMessage("AcceptAll"));
1064            } else if (_train.getLoadOption().equals(Train.INCLUDE_LOADS)) {
1065                loadOptionButton.setText(Bundle.getMessage(
1066                        "AcceptOnly") + " " + _train.getLoadNames().length + " " + Bundle.getMessage("Loads"));
1067            } else {
1068                loadOptionButton.setText(Bundle.getMessage(
1069                        "Exclude") + " " + _train.getLoadNames().length + " " + Bundle.getMessage("Loads"));
1070            }
1071            if (!_train.getCarRoadOption().equals(Train.ALL_ROADS) ||
1072                    !_train.getCabooseRoadOption().equals(Train.ALL_ROADS) ||
1073                    !_train.getLocoRoadOption().equals(Train.ALL_ROADS) ||
1074                    !_train.getLoadOption().equals(Train.ALL_LOADS)) {
1075                roadAndLoadStatusPanel.setVisible(true);
1076            }
1077        }
1078    }
1079
1080    List<Frame> children = new ArrayList<>();
1081
1082    public void setChildFrame(Frame frame) {
1083        if (children.contains(frame)) {
1084            return;
1085        }
1086        children.add(frame);
1087    }
1088
1089    @Override
1090    public void dispose() {
1091        InstanceManager.getDefault(LocationManager.class).removePropertyChangeListener(this);
1092        InstanceManager.getDefault(EngineTypes.class).removePropertyChangeListener(this);
1093        InstanceManager.getDefault(EngineModels.class).removePropertyChangeListener(this);
1094        InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this);
1095        InstanceManager.getDefault(CarRoads.class).removePropertyChangeListener(this);
1096        routeManager.removePropertyChangeListener(this);
1097        for (Frame frame : children) {
1098            frame.dispose();
1099        }
1100        if (_train != null) {
1101            _train.removePropertyChangeListener(this);
1102            Route route = _train.getRoute();
1103            if (route != null) {
1104                for (RouteLocation rl : route.getLocationsBySequenceList()) {
1105                    Location loc = rl.getLocation();
1106                    if (loc != null) {
1107                        loc.removePropertyChangeListener(this);
1108                    }
1109                }
1110            }
1111        }
1112        super.dispose();
1113    }
1114
1115    @Override
1116    public void propertyChange(java.beans.PropertyChangeEvent e) {
1117        if (Control.SHOW_PROPERTY) {
1118            log.debug("Property change ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(),
1119                    e.getNewValue()); // NOI18N
1120        }
1121        if (e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY) ||
1122                e.getPropertyName().equals(Train.TYPES_CHANGED_PROPERTY)) {
1123            updateCarTypeCheckboxes();
1124        }
1125        if (e.getPropertyName().equals(EngineTypes.ENGINETYPES_CHANGED_PROPERTY)) {
1126            updateEngineTypeCheckboxes();
1127        }
1128        if (e.getPropertyName().equals(RouteManager.LISTLENGTH_CHANGED_PROPERTY)) {
1129            updateRouteComboBox();
1130        }
1131        if (e.getPropertyName().equals(Route.LISTCHANGE_CHANGED_PROPERTY) ||
1132                e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY) ||
1133                e.getPropertyName().equals(Location.NAME_CHANGED_PROPERTY) ||
1134                e.getPropertyName().equals(Location.TRAIN_DIRECTION_CHANGED_PROPERTY)) {
1135            updateLocationCheckboxes();
1136            pack();
1137            repaint();
1138        }
1139        if (e.getPropertyName().equals(CarRoads.CARROADS_CHANGED_PROPERTY)) {
1140            updateRoadComboBoxes();
1141        }
1142        if (e.getPropertyName().equals(EngineModels.ENGINEMODELS_CHANGED_PROPERTY)) {
1143            InstanceManager.getDefault(EngineModels.class).updateComboBox(modelEngineBox);
1144            modelEngineBox.insertItemAt(NONE, 0);
1145            modelEngineBox.setSelectedIndex(0);
1146            if (_train != null) {
1147                modelEngineBox.setSelectedItem(_train.getEngineModel());
1148            }
1149        }
1150        if (e.getPropertyName().equals(Train.DEPARTURETIME_CHANGED_PROPERTY)) {
1151            updateDepartureTime();
1152        }
1153        if (e.getPropertyName().equals(Train.TRAIN_ROUTE_CHANGED_PROPERTY) && _train != null) {
1154            routeBox.setSelectedItem(_train.getRoute());
1155        }
1156        if (e.getPropertyName().equals(Route.ROUTE_STATUS_CHANGED_PROPERTY)) {
1157            updateDepartureTime();
1158            enableButtons(_train != null);
1159            updateRouteStatus();
1160        }
1161        if (e.getPropertyName().equals(Train.ROADS_CHANGED_PROPERTY) ||
1162                e.getPropertyName().equals(Train.LOADS_CHANGED_PROPERTY)) {
1163            updateRoadAndLoadStatus();
1164        }
1165    }
1166
1167    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainEditFrame.class);
1168}