001package jmri.jmrit.operations.trains.gui;
002
003import java.awt.*;
004import java.util.List;
005
006import javax.swing.*;
007
008import jmri.InstanceManager;
009import jmri.jmrit.operations.OperationsFrame;
010import jmri.jmrit.operations.OperationsXml;
011import jmri.jmrit.operations.rollingstock.cars.*;
012import jmri.jmrit.operations.rollingstock.engines.EngineManager;
013import jmri.jmrit.operations.rollingstock.engines.EngineModels;
014import jmri.jmrit.operations.routes.RouteLocation;
015import jmri.jmrit.operations.setup.Control;
016import jmri.jmrit.operations.setup.Setup;
017import jmri.jmrit.operations.trains.Train;
018import jmri.util.swing.JmriJOptionPane;
019
020/**
021 * Frame for user edit of a train's build options
022 *
023 * @author Dan Boudreau Copyright (C) 2010, 2012, 2013, 2024
024 */
025public class TrainEditBuildOptionsFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
026
027    Train _train = null;
028
029    JPanel panelOwnerNames = new JPanel();
030    JPanel panelBuilt = new JPanel();
031    JPanel panelTrainReq1 = new JPanel();
032    JPanel panelTrainReq2 = new JPanel();
033
034    JScrollPane ownerPane;
035    JScrollPane builtPane;
036    JScrollPane trainReq1Pane;
037    JScrollPane trainReq2Pane;
038
039    JPanel engine1Option = new JPanel();
040    JPanel engine1DropOption = new JPanel();
041    JPanel engine1caboose = new JPanel();
042
043    JPanel engine2Option = new JPanel();
044    JPanel engine2DropOption = new JPanel();
045    JPanel engine2caboose = new JPanel();
046
047    // labels
048    JLabel trainName = new JLabel();
049    JLabel trainDescription = new JLabel();
050    JLabel before = new JLabel(Bundle.getMessage("Before"));
051    JLabel after = new JLabel(Bundle.getMessage("After"));
052
053    // major buttons
054    JButton addOwnerButton = new JButton(Bundle.getMessage("AddOwner"));
055    JButton deleteOwnerButton = new JButton(Bundle.getMessage("DeleteOwner"));
056    JButton saveTrainButton = new JButton(Bundle.getMessage("SaveTrain"));
057
058    // radio buttons
059    JRadioButton ownerNameAll = new JRadioButton(Bundle.getMessage("AcceptAll"));
060    JRadioButton ownerNameInclude = new JRadioButton(Bundle.getMessage("AcceptOnly"));
061    JRadioButton ownerNameExclude = new JRadioButton(Bundle.getMessage("Exclude"));
062
063    JRadioButton builtDateAll = new JRadioButton(Bundle.getMessage("AcceptAll"));
064    JRadioButton builtDateAfter = new JRadioButton(Bundle.getMessage("After"));
065    JRadioButton builtDateBefore = new JRadioButton(Bundle.getMessage("Before"));
066    JRadioButton builtDateRange = new JRadioButton(Bundle.getMessage("Range"));
067
068    ButtonGroup ownerGroup = new ButtonGroup();
069    ButtonGroup builtGroup = new ButtonGroup();
070
071    // train requirements 1st set
072    JRadioButton none1 = new JRadioButton(Bundle.getMessage("None"));
073    JRadioButton change1Engine = new JRadioButton(Bundle.getMessage("EngineChange"));
074    JRadioButton add1Engine = new JRadioButton(Bundle.getMessage("AddEngines"));
075    JRadioButton remove1Engine = new JRadioButton(Bundle.getMessage("RemoveEngines"));
076    JRadioButton modify1Caboose = new JRadioButton(Bundle.getMessage("ChangeCaboose"));
077    JRadioButton helper1Service = new JRadioButton(Bundle.getMessage("HelperService"));
078    JRadioButton remove1Caboose = new JRadioButton(Bundle.getMessage("RemoveCaboose"));
079    JRadioButton keep1Caboose = new JRadioButton(Bundle.getMessage("KeepCaboose"));
080    JRadioButton change1Caboose = new JRadioButton(Bundle.getMessage("ChangeCaboose"));
081
082    ButtonGroup trainReq1Group = new ButtonGroup();
083    ButtonGroup cabooseOption1Group = new ButtonGroup();
084
085    // train requirements 2nd set
086    JRadioButton none2 = new JRadioButton(Bundle.getMessage("None"));
087    JRadioButton change2Engine = new JRadioButton(Bundle.getMessage("EngineChange"));
088    JRadioButton add2Engine = new JRadioButton(Bundle.getMessage("AddEngines"));
089    JRadioButton remove2Engine = new JRadioButton(Bundle.getMessage("RemoveEngines"));
090    JRadioButton modify2Caboose = new JRadioButton(Bundle.getMessage("ChangeCaboose"));
091    JRadioButton helper2Service = new JRadioButton(Bundle.getMessage("HelperService"));
092    JRadioButton remove2Caboose = new JRadioButton(Bundle.getMessage("RemoveCaboose"));
093    JRadioButton keep2Caboose = new JRadioButton(Bundle.getMessage("KeepCaboose"));
094    JRadioButton change2Caboose = new JRadioButton(Bundle.getMessage("ChangeCaboose"));
095
096    ButtonGroup trainReq2Group = new ButtonGroup();
097    ButtonGroup cabooseOption2Group = new ButtonGroup();
098
099    // check boxes
100    JCheckBox buildNormalCheckBox = new JCheckBox(Bundle.getMessage("NormalModeWhenBuilding"));
101    JCheckBox sendToTerminalCheckBox = new JCheckBox();
102    JCheckBox returnStagingCheckBox = new JCheckBox(Bundle.getMessage("AllowCarsToReturn"));
103    JCheckBox allowLocalMovesCheckBox = new JCheckBox(Bundle.getMessage("AllowLocalMoves"));
104    JCheckBox allowThroughCarsCheckBox = new JCheckBox(Bundle.getMessage("AllowThroughCars"));
105    JCheckBox serviceAllCarsCheckBox = new JCheckBox(Bundle.getMessage("ServiceAllCars"));
106    JCheckBox sendCustomStagngCheckBox = new JCheckBox(Bundle.getMessage("SendCustomToStaging"));
107    JCheckBox buildConsistCheckBox = new JCheckBox(Bundle.getMessage("BuildConsist"));
108
109    // text field
110    JTextField builtAfterTextField = new JTextField(10);
111    JTextField builtBeforeTextField = new JTextField(10);
112
113    // combo boxes
114    JComboBox<String> ownerBox = InstanceManager.getDefault(CarOwners.class).getComboBox();
115
116    // train requirements 1st set
117    JComboBox<RouteLocation> routePickup1Box = new JComboBox<>();
118    JComboBox<RouteLocation> routeDrop1Box = new JComboBox<>();
119    JComboBox<String> roadCaboose1Box = new JComboBox<>();
120    JComboBox<String> roadEngine1Box = InstanceManager.getDefault(CarRoads.class).getComboBox();
121    JComboBox<String> modelEngine1Box = InstanceManager.getDefault(EngineModels.class).getComboBox();
122    JComboBox<String> numEngines1Box = new JComboBox<>();
123
124    // train requirements 2nd set
125    JComboBox<RouteLocation> routePickup2Box = new JComboBox<>();
126    JComboBox<RouteLocation> routeDrop2Box = new JComboBox<>();
127    JComboBox<String> roadCaboose2Box = new JComboBox<>();
128    JComboBox<String> roadEngine2Box = InstanceManager.getDefault(CarRoads.class).getComboBox();
129    JComboBox<String> modelEngine2Box = InstanceManager.getDefault(EngineModels.class).getComboBox();
130    JComboBox<String> numEngines2Box = new JComboBox<>();
131
132    public static final String DISPOSE = "dispose"; // NOI18N
133
134    public TrainEditBuildOptionsFrame() {
135        super(Bundle.getMessage("MenuItemBuildOptions"));
136    }
137
138    public void initComponents(TrainEditFrame parent) {
139
140        ownerPane = new JScrollPane(panelOwnerNames);
141        ownerPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
142        ownerPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("OwnersTrain")));
143
144        builtPane = new JScrollPane(panelBuilt);
145        builtPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
146        builtPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BuiltDatesTrain")));
147
148        trainReq1Pane = new JScrollPane(panelTrainReq1);
149        trainReq1Pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
150        trainReq1Pane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainRequires")));
151
152        trainReq2Pane = new JScrollPane(panelTrainReq2);
153        trainReq2Pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
154        trainReq2Pane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainRequires")));
155
156        parent.setChildFrame(this);
157        _train = parent._train;
158
159        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
160
161        // Layout the panel by rows
162        JPanel p1 = new JPanel();
163        p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
164        p1.setMaximumSize(new Dimension(2000, 250));
165
166        // Layout the panel by rows
167        // row 1a
168        JPanel pName = new JPanel();
169        pName.setLayout(new GridBagLayout());
170        pName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Name")));
171        addItem(pName, trainName, 0, 0);
172
173        // row 1b
174        JPanel pDesc = new JPanel();
175        pDesc.setLayout(new GridBagLayout());
176        pDesc.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Description")));
177        addItem(pDesc, trainDescription, 0, 0);
178
179        p1.add(pName);
180        p1.add(pDesc);
181
182        // row 2
183        JPanel pOption = new JPanel();
184        pOption.setLayout(new GridBagLayout());
185        pOption.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Options")));
186        addItemLeft(pOption, buildNormalCheckBox, 0, 0);
187        addItemLeft(pOption, sendToTerminalCheckBox, 1, 0);
188        addItemLeft(pOption, returnStagingCheckBox, 0, 1);
189        addItemLeft(pOption, allowLocalMovesCheckBox, 1, 1);
190        addItemLeft(pOption, allowThroughCarsCheckBox, 0, 2);
191        addItemLeft(pOption, serviceAllCarsCheckBox, 1, 2);
192        addItemLeft(pOption, sendCustomStagngCheckBox, 0, 3);
193        addItemLeft(pOption, buildConsistCheckBox, 1, 3);
194        pOption.setMaximumSize(new Dimension(2000, 250));
195
196        buildNormalCheckBox.setEnabled(Setup.isBuildAggressive());
197        returnStagingCheckBox.setEnabled(false); // only enable if train departs and returns to same staging loc
198
199        // row 7
200        panelOwnerNames.setLayout(new GridBagLayout());
201        ownerGroup.add(ownerNameAll);
202        ownerGroup.add(ownerNameInclude);
203        ownerGroup.add(ownerNameExclude);
204
205        // row 9
206        panelBuilt.setLayout(new GridBagLayout());
207        builtAfterTextField.setToolTipText(Bundle.getMessage("EnterYearTip"));
208        builtBeforeTextField.setToolTipText(Bundle.getMessage("EnterYearTip"));
209        addItem(panelBuilt, builtDateAll, 0, 0);
210        addItem(panelBuilt, builtDateAfter, 1, 0);
211        addItem(panelBuilt, builtDateBefore, 2, 0);
212        addItem(panelBuilt, builtDateRange, 3, 0);
213        addItem(panelBuilt, after, 1, 1);
214        addItem(panelBuilt, builtAfterTextField, 2, 1);
215        addItem(panelBuilt, before, 1, 2);
216        addItem(panelBuilt, builtBeforeTextField, 2, 2);
217        builtGroup.add(builtDateAll);
218        builtGroup.add(builtDateAfter);
219        builtGroup.add(builtDateBefore);
220        builtGroup.add(builtDateRange);
221
222        // row 11
223        panelTrainReq1.setLayout(new BoxLayout(panelTrainReq1, BoxLayout.Y_AXIS));
224
225        JPanel trainOption1 = new JPanel();
226        trainOption1.setLayout(new GridBagLayout());
227        addItem(trainOption1, none1, 0, 0);
228        addItem(trainOption1, change1Engine, 1, 0);
229        addItem(trainOption1, add1Engine, 2, 0);
230        addItem(trainOption1, remove1Engine, 3, 0);
231        addItem(trainOption1, modify1Caboose, 1, 1);
232        addItem(trainOption1, helper1Service, 2, 1);
233        panelTrainReq1.add(trainOption1);
234
235        trainReq1Group.add(none1);
236        trainReq1Group.add(change1Engine);
237        trainReq1Group.add(add1Engine);
238        trainReq1Group.add(remove1Engine);
239        trainReq1Group.add(modify1Caboose);
240        trainReq1Group.add(helper1Service);
241
242        // engine options
243        engine1Option.setLayout(new GridBagLayout());
244
245        for (int i = 0; i < Setup.getMaxNumberEngines() + 1; i++) {
246            numEngines1Box.addItem(Integer.toString(i));
247        }
248        numEngines1Box.addItem(Train.AUTO_HPT);
249        numEngines1Box.setMinimumSize(new Dimension(50, 20));
250        modelEngine1Box.insertItemAt("", 0);
251        modelEngine1Box.setSelectedIndex(0);
252        modelEngine1Box.setMinimumSize(new Dimension(120, 20));
253        modelEngine1Box.setToolTipText(Bundle.getMessage("ModelEngineTip"));
254        roadEngine1Box.insertItemAt("", 0);
255        roadEngine1Box.setSelectedIndex(0);
256        roadEngine1Box.setMinimumSize(new Dimension(120, 20));
257        roadEngine1Box.setToolTipText(Bundle.getMessage("RoadEngineTip"));
258        panelTrainReq1.add(engine1Option);
259
260        // caboose options
261        engine1caboose.setLayout(new GridBagLayout());
262        engine1caboose.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ChangeCaboose")));
263        roadCaboose1Box.setMinimumSize(new Dimension(120, 20));
264        roadCaboose1Box.setToolTipText(Bundle.getMessage("RoadCabooseTip"));
265        panelTrainReq1.add(engine1caboose);
266
267        cabooseOption1Group.add(remove1Caboose);
268        cabooseOption1Group.add(keep1Caboose);
269        cabooseOption1Group.add(change1Caboose);
270
271        // drop engine panel
272        addItem(engine1DropOption, new JLabel(Bundle.getMessage("DropEnginesAt")), 0, 0);
273        addItem(engine1DropOption, routeDrop1Box, 1, 0);
274        panelTrainReq1.add(engine1DropOption);
275
276        // row 13
277        panelTrainReq2.setLayout(new BoxLayout(panelTrainReq2, BoxLayout.Y_AXIS));
278
279        JPanel trainOption2 = new JPanel();
280        trainOption2.setLayout(new GridBagLayout());
281        addItem(trainOption2, none2, 0, 0);
282        addItem(trainOption2, change2Engine, 1, 0);
283        addItem(trainOption2, add2Engine, 2, 0);
284        addItem(trainOption2, remove2Engine, 3, 0);
285        addItem(trainOption2, modify2Caboose, 1, 1);
286        addItem(trainOption2, helper2Service, 2, 1);
287        panelTrainReq2.add(trainOption2);
288
289        trainReq2Group.add(none2);
290        trainReq2Group.add(change2Engine);
291        trainReq2Group.add(add2Engine);
292        trainReq2Group.add(remove2Engine);
293        trainReq2Group.add(modify2Caboose);
294        trainReq2Group.add(helper2Service);
295
296        // engine options
297        engine2Option.setLayout(new GridBagLayout());
298
299        for (int i = 0; i < Setup.getMaxNumberEngines() + 1; i++) {
300            numEngines2Box.addItem(Integer.toString(i));
301        }
302        numEngines2Box.addItem(Train.AUTO_HPT);
303        numEngines2Box.setMinimumSize(new Dimension(50, 20));
304        modelEngine2Box.insertItemAt("", 0);
305        modelEngine2Box.setSelectedIndex(0);
306        modelEngine2Box.setMinimumSize(new Dimension(120, 20));
307        modelEngine2Box.setToolTipText(Bundle.getMessage("ModelEngineTip"));
308        roadEngine2Box.insertItemAt("", 0);
309        roadEngine2Box.setSelectedIndex(0);
310        roadEngine2Box.setMinimumSize(new Dimension(120, 20));
311        roadEngine2Box.setToolTipText(Bundle.getMessage("RoadEngineTip"));
312        panelTrainReq2.add(engine2Option);
313
314        // caboose options
315        engine2caboose.setLayout(new GridBagLayout());
316        engine2caboose.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ChangeCaboose")));
317        roadCaboose2Box.setMinimumSize(new Dimension(120, 20));
318        roadCaboose2Box.setToolTipText(Bundle.getMessage("RoadCabooseTip"));
319        panelTrainReq2.add(engine2caboose);
320
321        cabooseOption2Group.add(remove2Caboose);
322        cabooseOption2Group.add(keep2Caboose);
323        cabooseOption2Group.add(change2Caboose);
324
325        // drop engine panel
326        addItem(engine2DropOption, new JLabel(Bundle.getMessage("DropEnginesAt")), 0, 0);
327        addItem(engine2DropOption, routeDrop2Box, 1, 0);
328        panelTrainReq2.add(engine2DropOption);
329
330        // row 15 buttons
331        JPanel pB = new JPanel();
332        pB.setLayout(new GridBagLayout());
333        //  pB.setMaximumSize(new Dimension(2000, 250));
334        addItem(pB, saveTrainButton, 3, 0);
335
336        getContentPane().add(p1);
337        getContentPane().add(pOption);
338        getContentPane().add(ownerPane);
339        getContentPane().add(builtPane);
340        getContentPane().add(trainReq1Pane);
341        getContentPane().add(trainReq2Pane);
342        getContentPane().add(pB);
343
344        // setup buttons
345        addButtonAction(deleteOwnerButton);
346        addButtonAction(addOwnerButton);
347        addButtonAction(saveTrainButton);
348
349        addRadioButtonAction(ownerNameAll);
350        addRadioButtonAction(ownerNameInclude);
351        addRadioButtonAction(ownerNameExclude);
352
353        addRadioButtonAction(builtDateAll);
354        addRadioButtonAction(builtDateAfter);
355        addRadioButtonAction(builtDateBefore);
356        addRadioButtonAction(builtDateRange);
357
358        addRadioButtonAction(none1);
359        addRadioButtonAction(change1Engine);
360        addRadioButtonAction(add1Engine);
361        addRadioButtonAction(remove1Engine);
362        addRadioButtonAction(modify1Caboose);
363        addRadioButtonAction(helper1Service);
364        addRadioButtonAction(remove1Caboose);
365        addRadioButtonAction(keep1Caboose);
366        addRadioButtonAction(change1Caboose);
367
368        addRadioButtonAction(none2);
369        addRadioButtonAction(change2Engine);
370        addRadioButtonAction(add2Engine);
371        addRadioButtonAction(remove2Engine);
372        addRadioButtonAction(modify2Caboose);
373        addRadioButtonAction(helper2Service);
374        addRadioButtonAction(remove2Caboose);
375        addRadioButtonAction(keep2Caboose);
376        addRadioButtonAction(change2Caboose);
377
378        addComboBoxAction(numEngines1Box);
379        addComboBoxAction(modelEngine1Box);
380        addComboBoxAction(numEngines2Box);
381        addComboBoxAction(modelEngine2Box);
382
383        if (_train != null) {
384            trainName.setText(_train.getName());
385            trainDescription.setText(_train.getDescription());
386            buildNormalCheckBox.setSelected(_train.isBuildTrainNormalEnabled());
387            sendToTerminalCheckBox.setSelected(_train.isSendCarsToTerminalEnabled());
388            allowLocalMovesCheckBox.setSelected(_train.isAllowLocalMovesEnabled());
389            allowThroughCarsCheckBox.setSelected(_train.isAllowThroughCarsEnabled());
390            serviceAllCarsCheckBox.setSelected(_train.isServiceAllCarsWithFinalDestinationsEnabled());
391            sendCustomStagngCheckBox.setSelected(_train.isSendCarsWithCustomLoadsToStagingEnabled());
392            buildConsistCheckBox.setSelected(_train.isBuildConsistEnabled());
393            sendToTerminalCheckBox.setText(Bundle.getMessage("SendToTerminal",
394                    _train.getTrainTerminatesName()));
395            builtAfterTextField.setText(_train.getBuiltStartYear());
396            builtBeforeTextField.setText(_train.getBuiltEndYear());
397            setBuiltRadioButton();
398            enableButtons(true);
399            // does train depart and return to same staging location?
400            updateReturnToStagingCheckbox();
401            // remove engines feature disabled when departing staging
402            updateRemoveEnginesRadioButtons();
403            // listen for train changes
404            _train.addPropertyChangeListener(this);
405        } else {
406            enableButtons(false);
407        }
408        addHelpMenu("package.jmri.jmrit.operations.Operations_TrainBuildOptions", true); // NOI18N
409        updateOwnerNames();
410        updateBuilt();
411        updateTrainRequires1Option();
412        updateTrainRequires2Option();
413
414        // get notified if car owners or engine models gets modified
415        InstanceManager.getDefault(CarOwners.class).addPropertyChangeListener(this);
416        InstanceManager.getDefault(EngineModels.class).addPropertyChangeListener(this);
417
418        // get notified if return to staging option changes
419        Setup.getDefault().addPropertyChangeListener(this);
420
421        initMinimumSize(new Dimension(Control.panelWidth700, Control.panelHeight600));
422    }
423
424    // Save
425    @Override
426    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
427        if (_train != null) {
428            if (ae.getSource() == saveTrainButton) {
429                log.debug("train save button activated");
430                saveTrain();
431            }
432            if (ae.getSource() == addOwnerButton) {
433                if (_train.addOwnerName((String) ownerBox.getSelectedItem())) {
434                    updateOwnerNames();
435                }
436                selectNextItemComboBox(ownerBox);
437            }
438            if (ae.getSource() == deleteOwnerButton) {
439                if (_train.deleteOwnerName((String) ownerBox.getSelectedItem())) {
440                    updateOwnerNames();
441                }
442                selectNextItemComboBox(ownerBox);
443            }
444        }
445    }
446
447    @Override
448    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
449        log.debug("radio button activated");
450        if (_train != null) {
451            if (ae.getSource() == ownerNameAll) {
452                _train.setOwnerOption(Train.ALL_OWNERS);
453                updateOwnerNames();
454            }
455            if (ae.getSource() == ownerNameInclude) {
456                _train.setOwnerOption(Train.INCLUDE_OWNERS);
457                updateOwnerNames();
458            }
459            if (ae.getSource() == ownerNameExclude) {
460                _train.setOwnerOption(Train.EXCLUDE_OWNERS);
461                updateOwnerNames();
462            }
463            if (ae.getSource() == builtDateAll ||
464                    ae.getSource() == builtDateAfter ||
465                    ae.getSource() == builtDateBefore ||
466                    ae.getSource() == builtDateRange) {
467                updateBuilt();
468            }
469            if (ae.getSource() == none1) {
470                _train.setSecondLegOptions(Train.NO_CABOOSE_OR_FRED);
471                updateTrainRequires1Option();
472                updateTrainRequires2Option();
473            }
474            if (ae.getSource() == change1Engine) {
475                _train.setSecondLegOptions(Train.CHANGE_ENGINES);
476                updateTrainRequires1Option();
477                updateTrainRequires2Option();
478            }
479            if (ae.getSource() == add1Engine) {
480                _train.setSecondLegOptions(Train.ADD_ENGINES);
481                updateTrainRequires1Option();
482                updateTrainRequires2Option();
483            }
484            if (ae.getSource() == remove1Engine) {
485                _train.setSecondLegOptions(Train.REMOVE_ENGINES);
486                updateTrainRequires1Option();
487                updateTrainRequires2Option();
488            }
489            if (ae.getSource() == modify1Caboose) {
490                _train.setSecondLegOptions(Train.ADD_CABOOSE);
491                updateTrainRequires1Option();
492                updateTrainRequires2Option();
493            }
494            if (ae.getSource() == helper1Service) {
495                _train.setSecondLegOptions(Train.HELPER_ENGINES);
496                updateTrainRequires1Option();
497            }
498            if (ae.getSource() == keep1Caboose ||
499                    ae.getSource() == change1Caboose ||
500                    ae.getSource() == remove1Caboose) {
501                roadCaboose1Box.setEnabled(change1Caboose.isSelected());
502                updateTrainRequires2Option();
503            }
504            if (ae.getSource() == none2) {
505                _train.setThirdLegOptions(Train.NO_CABOOSE_OR_FRED);
506                updateTrainRequires2Option();
507            }
508            if (ae.getSource() == change2Engine) {
509                _train.setThirdLegOptions(Train.CHANGE_ENGINES);
510                updateTrainRequires2Option();
511            }
512            if (ae.getSource() == add2Engine) {
513                _train.setThirdLegOptions(Train.ADD_ENGINES);
514                updateTrainRequires2Option();
515            }
516            if (ae.getSource() == remove2Engine) {
517                _train.setThirdLegOptions(Train.REMOVE_ENGINES);
518                updateTrainRequires2Option();
519            }
520            if (ae.getSource() == modify2Caboose) {
521                _train.setThirdLegOptions(Train.ADD_CABOOSE);
522                updateTrainRequires2Option();
523            }
524            if (ae.getSource() == helper2Service) {
525                _train.setThirdLegOptions(Train.HELPER_ENGINES);
526                updateTrainRequires2Option();
527            }
528            if (ae.getSource() == keep2Caboose ||
529                    ae.getSource() == change2Caboose ||
530                    ae.getSource() == remove2Caboose) {
531                roadCaboose2Box.setEnabled(change2Caboose.isSelected());
532            }
533        }
534    }
535
536    // Car type combo box has been changed, show loads associated with this car type
537    @Override
538    public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
539        if (ae.getSource() == numEngines1Box) {
540            modelEngine1Box.setEnabled(!numEngines1Box.getSelectedItem().equals("0"));
541            roadEngine1Box.setEnabled(!numEngines1Box.getSelectedItem().equals("0"));
542        }
543        if (ae.getSource() == modelEngine1Box) {
544            updateEngineRoadComboBox(roadEngine1Box, (String) modelEngine1Box.getSelectedItem());
545            if (_train != null) {
546                roadEngine1Box.setSelectedItem(_train.getSecondLegEngineRoad());
547            }
548        }
549        if (ae.getSource() == numEngines2Box) {
550            modelEngine2Box.setEnabled(!numEngines2Box.getSelectedItem().equals("0"));
551            roadEngine2Box.setEnabled(!numEngines2Box.getSelectedItem().equals("0"));
552        }
553        if (ae.getSource() == modelEngine2Box) {
554            updateEngineRoadComboBox(roadEngine2Box, (String) modelEngine2Box.getSelectedItem());
555            if (_train != null) {
556                roadEngine2Box.setSelectedItem(_train.getThirdLegEngineRoad());
557            }
558        }
559    }
560
561    private void updateOwnerNames() {
562        panelOwnerNames.removeAll();
563
564        JPanel p = new JPanel();
565        p.setLayout(new GridBagLayout());
566        p.add(ownerNameAll, 0);
567        p.add(ownerNameInclude, 1);
568        p.add(ownerNameExclude, 2);
569        GridBagConstraints gc = new GridBagConstraints();
570        gc.gridwidth = 6;
571        panelOwnerNames.add(p, gc);
572
573        int y = 1; // vertical position in panel
574
575        if (_train != null) {
576            // set radio button
577            ownerNameAll.setSelected(_train.getOwnerOption().equals(Train.ALL_OWNERS));
578            ownerNameInclude.setSelected(_train.getOwnerOption().equals(Train.INCLUDE_OWNERS));
579            ownerNameExclude.setSelected(_train.getOwnerOption().equals(Train.EXCLUDE_OWNERS));
580
581            if (!ownerNameAll.isSelected()) {
582                p = new JPanel();
583                p.setLayout(new FlowLayout());
584                p.add(ownerBox);
585                p.add(addOwnerButton);
586                p.add(deleteOwnerButton);
587                gc.gridy = y++;
588                panelOwnerNames.add(p, gc);
589
590                int x = 0;
591                for (String ownerName : _train.getOwnerNames()) {
592                    JLabel owner = new JLabel();
593                    owner.setText(ownerName);
594                    addItem(panelOwnerNames, owner, x++, y);
595                    if (x > 6) {
596                        y++;
597                        x = 0;
598                    }
599                }
600            }
601        } else {
602            ownerNameAll.setSelected(true);
603        }
604        panelOwnerNames.revalidate();
605        panelOwnerNames.repaint();
606        revalidate();
607    }
608
609    private void setBuiltRadioButton() {
610        if (_train.getBuiltStartYear().equals(Train.NONE) && _train.getBuiltEndYear().equals(Train.NONE)) {
611            builtDateAll.setSelected(true);
612        } else if (!_train.getBuiltStartYear().equals(Train.NONE) && !_train.getBuiltEndYear().equals(Train.NONE)) {
613            builtDateRange.setSelected(true);
614        } else if (!_train.getBuiltStartYear().equals(Train.NONE)) {
615            builtDateAfter.setSelected(true);
616        } else if (!_train.getBuiltEndYear().equals(Train.NONE)) {
617            builtDateBefore.setSelected(true);
618        }
619    }
620
621    private void updateBuilt() {
622        builtAfterTextField.setVisible(false);
623        builtBeforeTextField.setVisible(false);
624        after.setVisible(false);
625        before.setVisible(false);
626        if (builtDateAll.isSelected()) {
627            builtAfterTextField.setText("");
628            builtBeforeTextField.setText("");
629        } else if (builtDateAfter.isSelected()) {
630            builtBeforeTextField.setText("");
631            builtAfterTextField.setVisible(true);
632            after.setVisible(true);
633        } else if (builtDateBefore.isSelected()) {
634            builtAfterTextField.setText("");
635            builtBeforeTextField.setVisible(true);
636            before.setVisible(true);
637        } else if (builtDateRange.isSelected()) {
638            after.setVisible(true);
639            before.setVisible(true);
640            builtAfterTextField.setVisible(true);
641            builtBeforeTextField.setVisible(true);
642        }
643        revalidate();
644    }
645
646    private void updateTrainRequires1Option() {
647        none1.setSelected(true);
648        if (_train != null) {
649
650            updateCabooseRoadComboBox(roadCaboose1Box);
651            updateEngineRoadComboBox(roadEngine1Box, (String) modelEngine1Box.getSelectedItem());
652            if (_train.getRoute() != null) {
653                _train.getRoute().updateComboBox(routePickup1Box);
654                _train.getRoute().updateComboBox(routeDrop1Box);
655            }
656
657            change1Engine.setSelected((_train.getSecondLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES);
658            add1Engine.setSelected((_train.getSecondLegOptions() & Train.ADD_ENGINES) == Train.ADD_ENGINES);
659            remove1Engine.setSelected((_train.getSecondLegOptions() & Train.REMOVE_ENGINES) == Train.REMOVE_ENGINES);
660            helper1Service.setSelected((_train.getSecondLegOptions() & Train.HELPER_ENGINES) == Train.HELPER_ENGINES);
661            if (!change1Engine.isSelected() &&
662                    !add1Engine.isSelected() &&
663                    !remove1Engine.isSelected() &&
664                    !helper1Service.isSelected()) {
665                modify1Caboose.setSelected((_train.getSecondLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE ||
666                        (_train.getSecondLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE);
667            }
668            numEngines1Box.setSelectedItem(_train.getSecondLegNumberEngines());
669            modelEngine1Box.setSelectedItem(_train.getSecondLegEngineModel());
670            routePickup1Box.setSelectedItem(_train.getSecondLegStartRouteLocation());
671            routeDrop1Box.setSelectedItem(_train.getSecondLegEndRouteLocation());
672            roadEngine1Box.setSelectedItem(_train.getSecondLegEngineRoad());
673            keep1Caboose.setSelected(true);
674            remove1Caboose.setSelected((_train.getSecondLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE);
675            change1Caboose.setSelected((_train.getSecondLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE);
676            roadCaboose1Box.setEnabled(change1Caboose.isSelected());
677            roadCaboose1Box.setSelectedItem(_train.getSecondLegCabooseRoad());
678            // adjust radio button text
679            if (_train.isCabooseNeeded()) {
680                change1Caboose.setText(Bundle.getMessage("ChangeCaboose"));
681                remove1Caboose.setEnabled(true);
682            } else {
683                change1Caboose.setText(Bundle.getMessage("AddCaboose"));
684                remove1Caboose.setEnabled(false);
685            }
686        }
687        engine1Option.setVisible(change1Engine.isSelected() ||
688                add1Engine.isSelected() ||
689                remove1Engine.isSelected() ||
690                helper1Service.isSelected());
691        engine1caboose.setVisible(change1Engine.isSelected() ||
692                add1Engine.isSelected() ||
693                remove1Engine.isSelected() ||
694                modify1Caboose.isSelected());
695        engine1DropOption.setVisible(helper1Service.isSelected());
696        if (change1Engine.isSelected()) {
697            engine1Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("EngineChange")));
698        } else if (add1Engine.isSelected()) {
699            engine1Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AddEngines")));
700        } else {
701            engine1Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RemoveEngines")));
702        }
703        if (helper1Service.isSelected()) {
704            engine1Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AddHelpers")));
705        }
706        if (change1Engine.isSelected() ||
707                add1Engine.isSelected() ||
708                remove1Engine.isSelected() ||
709                helper1Service.isSelected()) {
710            createEngine1Panel();
711        }
712        if (change1Engine.isSelected() ||
713                add1Engine.isSelected() ||
714                remove1Engine.isSelected() ||
715                modify1Caboose.isSelected()) {
716            createCaboose1Panel(modify1Caboose.isSelected());
717        }
718        revalidate();
719    }
720
721    private void updateTrainRequires2Option() {
722        none2.setSelected(true);
723        if (_train != null) {
724
725            updateCabooseRoadComboBox(roadCaboose2Box);
726            updateEngineRoadComboBox(roadEngine2Box, (String) modelEngine2Box.getSelectedItem());
727            if (_train.getRoute() != null) {
728                _train.getRoute().updateComboBox(routePickup2Box);
729                _train.getRoute().updateComboBox(routeDrop2Box);
730            }
731
732            change2Engine.setSelected((_train.getThirdLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES);
733            add2Engine.setSelected((_train.getThirdLegOptions() & Train.ADD_ENGINES) == Train.ADD_ENGINES);
734            remove2Engine.setSelected((_train.getThirdLegOptions() & Train.REMOVE_ENGINES) == Train.REMOVE_ENGINES);
735            helper2Service.setSelected((_train.getThirdLegOptions() & Train.HELPER_ENGINES) == Train.HELPER_ENGINES);
736            if (!change2Engine.isSelected() &&
737                    !add2Engine.isSelected() &&
738                    !remove2Engine.isSelected() &&
739                    !helper2Service.isSelected()) {
740                modify2Caboose.setSelected((_train.getThirdLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE ||
741                        (_train.getThirdLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE);
742            }
743            numEngines2Box.setSelectedItem(_train.getThirdLegNumberEngines());
744            modelEngine2Box.setSelectedItem(_train.getThirdLegEngineModel());
745            routePickup2Box.setSelectedItem(_train.getThirdLegStartRouteLocation());
746            routeDrop2Box.setSelectedItem(_train.getThirdLegEndRouteLocation());
747            roadEngine2Box.setSelectedItem(_train.getThirdLegEngineRoad());
748            keep2Caboose.setSelected(true);
749            remove2Caboose.setSelected((_train.getThirdLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE);
750            change2Caboose.setSelected((_train.getThirdLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE);
751            roadCaboose2Box.setEnabled(change2Caboose.isSelected());
752            roadCaboose2Box.setSelectedItem(_train.getThirdLegCabooseRoad());
753            // adjust radio button text
754            if ((_train.isCabooseNeeded() || change1Caboose.isSelected()) &&
755                    !remove1Caboose.isSelected()) {
756                change2Caboose.setText(Bundle.getMessage("ChangeCaboose"));
757                remove2Caboose.setEnabled(true);
758            } else {
759                change2Caboose.setText(Bundle.getMessage("AddCaboose"));
760                remove2Caboose.setEnabled(false);
761            }
762        }
763        engine2Option.setVisible(change2Engine.isSelected() ||
764                add2Engine.isSelected() ||
765                remove2Engine.isSelected() ||
766                helper2Service.isSelected());
767        engine2caboose.setVisible(change2Engine.isSelected() ||
768                add2Engine.isSelected() ||
769                remove2Engine.isSelected() ||
770                modify2Caboose.isSelected());
771        engine2DropOption.setVisible(helper2Service.isSelected());
772        if (change2Engine.isSelected()) {
773            engine2Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("EngineChange")));
774        } else if (add2Engine.isSelected()) {
775            engine2Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AddEngines")));
776        } else {
777            engine2Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RemoveEngines")));
778        }
779        if (helper2Service.isSelected()) {
780            engine2Option.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AddHelpers")));
781        }
782        if (change2Engine.isSelected() ||
783                add2Engine.isSelected() ||
784                remove2Engine.isSelected() ||
785                helper2Service.isSelected()) {
786            createEngine2Panel();
787        }
788        if (change2Engine.isSelected() ||
789                add2Engine.isSelected() ||
790                remove2Engine.isSelected() ||
791                modify2Caboose.isSelected()) {
792            createCaboose2Panel(modify2Caboose.isSelected());
793        }
794        revalidate();
795    }
796
797    private void saveTrain() {
798        if (!checkInput()) {
799            return;
800        }
801        _train.setBuildTrainNormalEnabled(buildNormalCheckBox.isSelected());
802        _train.setSendCarsToTerminalEnabled(sendToTerminalCheckBox.isSelected());
803        if (returnStagingCheckBox.isEnabled()) {
804            _train.setAllowReturnToStagingEnabled(returnStagingCheckBox.isSelected());
805        }
806        _train.setAllowLocalMovesEnabled(allowLocalMovesCheckBox.isSelected());
807        _train.setAllowThroughCarsEnabled(allowThroughCarsCheckBox.isSelected());
808        _train.setServiceAllCarsWithFinalDestinationsEnabled(serviceAllCarsCheckBox.isSelected());
809        _train.setSendCarsWithCustomLoadsToStagingEnabled(sendCustomStagngCheckBox.isSelected());
810        _train.setBuildConsistEnabled(buildConsistCheckBox.isSelected());
811        _train.setBuiltStartYear(builtAfterTextField.getText().trim());
812        _train.setBuiltEndYear(builtBeforeTextField.getText().trim());
813
814        int options1 = Train.NO_CABOOSE_OR_FRED;
815        if (change1Engine.isSelected()) {
816            options1 = options1 | Train.CHANGE_ENGINES;
817        }
818        if (add1Engine.isSelected()) {
819            options1 = options1 | Train.ADD_ENGINES;
820        }
821        if (remove1Engine.isSelected()) {
822            options1 = options1 | Train.REMOVE_ENGINES;
823        }
824        if (remove1Caboose.isSelected()) {
825            options1 = options1 | Train.REMOVE_CABOOSE;
826        } else if (change1Caboose.isSelected()) {
827            options1 = options1 | Train.ADD_CABOOSE | Train.REMOVE_CABOOSE;
828        }
829        if (helper1Service.isSelected()) {
830            options1 = options1 | Train.HELPER_ENGINES;
831        }
832        _train.setSecondLegOptions(options1);
833        if (routePickup1Box.getSelectedItem() != null) {
834            _train.setSecondLegStartRouteLocation((RouteLocation) routePickup1Box.getSelectedItem());
835        } else {
836            _train.setSecondLegStartRouteLocation(null);
837        }
838        if (routeDrop1Box.getSelectedItem() != null) {
839            _train.setSecondLegEndRouteLocation((RouteLocation) routeDrop1Box.getSelectedItem());
840        } else {
841            _train.setSecondLegEndRouteLocation(null);
842        }
843        _train.setSecondLegNumberEngines((String) numEngines1Box.getSelectedItem());
844        _train.setSecondLegEngineModel((String) modelEngine1Box.getSelectedItem());
845        _train.setSecondLegEngineRoad((String) roadEngine1Box.getSelectedItem());
846        _train.setSecondLegCabooseRoad((String) roadCaboose1Box.getSelectedItem());
847
848        int options2 = Train.NO_CABOOSE_OR_FRED;
849        if (change2Engine.isSelected()) {
850            options2 = options2 | Train.CHANGE_ENGINES;
851        }
852        if (add2Engine.isSelected()) {
853            options2 = options2 | Train.ADD_ENGINES;
854        }
855        if (remove2Engine.isSelected()) {
856            options2 = options2 | Train.REMOVE_ENGINES;
857        }
858        if (remove2Caboose.isSelected()) {
859            options2 = options2 | Train.REMOVE_CABOOSE;
860        } else if (change2Caboose.isSelected()) {
861            options2 = options2 | Train.ADD_CABOOSE | Train.REMOVE_CABOOSE;
862        }
863        if (helper2Service.isSelected()) {
864            options2 = options2 | Train.HELPER_ENGINES;
865        }
866        _train.setThirdLegOptions(options2);
867        if (routePickup2Box.getSelectedItem() != null) {
868            _train.setThirdLegStartRouteLocation((RouteLocation) routePickup2Box.getSelectedItem());
869        } else {
870            _train.setThirdLegStartRouteLocation(null);
871        }
872        if (routeDrop2Box.getSelectedItem() != null) {
873            _train.setThirdLegEndRouteLocation((RouteLocation) routeDrop2Box.getSelectedItem());
874        } else {
875            _train.setThirdLegEndRouteLocation(null);
876        }
877        _train.setThirdLegNumberEngines((String) numEngines2Box.getSelectedItem());
878        _train.setThirdLegEngineModel((String) modelEngine2Box.getSelectedItem());
879        _train.setThirdLegEngineRoad((String) roadEngine2Box.getSelectedItem());
880        _train.setThirdLegCabooseRoad((String) roadCaboose2Box.getSelectedItem());
881
882        OperationsXml.save();
883        if (Setup.isCloseWindowOnSaveEnabled()) {
884            dispose();
885        }
886    }
887
888    private boolean checkInput() {
889        if ((!none1.isSelected() && routePickup1Box.getSelectedItem() == null) ||
890                (!none2.isSelected() && routePickup2Box.getSelectedItem() == null)) {
891            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("SelectLocationEngChange"), Bundle
892                    .getMessage("CanNotSave"), JmriJOptionPane.ERROR_MESSAGE);
893            return false;
894        }
895        if ((helper1Service.isSelected() && routeDrop1Box.getSelectedItem() == null) ||
896                (helper2Service.isSelected() && routeDrop2Box.getSelectedItem() == null)) {
897            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("SelectLocationEndHelper"), Bundle
898                    .getMessage("CanNotSave"), JmriJOptionPane.ERROR_MESSAGE);
899            return false;
900        }
901        try {
902            if (!builtAfterTextField.getText().trim().isEmpty()) {
903                Integer.parseInt(builtAfterTextField.getText().trim());
904            }
905            if (!builtBeforeTextField.getText().trim().isEmpty()) {
906                Integer.parseInt(builtBeforeTextField.getText().trim());
907            }
908        } catch (NumberFormatException e) {
909            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("EnterFourDigitYear"), Bundle
910                    .getMessage("CanNotSave"), JmriJOptionPane.ERROR_MESSAGE);
911            return false;
912        }
913        if ((change1Engine.isSelected() && !checkModel(modelEngine1Box, numEngines1Box, roadEngine1Box)) ||
914                (change2Engine.isSelected() && !checkModel(modelEngine2Box, numEngines2Box, roadEngine2Box))) {
915            return false;
916        }
917        if ((add1Engine.isSelected() && !checkModel(modelEngine1Box, numEngines1Box, roadEngine1Box)) ||
918                (add2Engine.isSelected() && !checkModel(modelEngine2Box, numEngines2Box, roadEngine2Box))) {
919            return false;
920        }
921        if ((remove1Engine.isSelected() && !checkModel(modelEngine1Box, numEngines1Box, roadEngine1Box)) ||
922                (remove2Engine.isSelected() && !checkModel(modelEngine2Box, numEngines2Box, roadEngine2Box))) {
923            return false;
924        }
925        if (!checkCabooseRoad(roadCaboose1Box, change1Caboose)) {
926            return false;
927        }
928        if (!checkCabooseRoad(roadCaboose2Box, change2Caboose)) {
929            return false;
930        }
931
932        return true;
933    }
934
935    private boolean checkModel(JComboBox<String> modelEngineBox, JComboBox<String> numEnginesBox,
936            JComboBox<String> roadEngineBox) {
937        String model = (String) modelEngineBox.getSelectedItem();
938        if (numEnginesBox.getSelectedItem().equals("0") || model.equals(NONE)) {
939            return true;
940        }
941        String type = InstanceManager.getDefault(EngineModels.class).getModelType(model);
942        if (!_train.isTypeNameAccepted(type)) {
943            JmriJOptionPane.showMessageDialog(this,
944                    Bundle.getMessage("TrainModelService", model, type),
945                    Bundle.getMessage("CanNot", Bundle.getMessage("save")),
946                    JmriJOptionPane.ERROR_MESSAGE);
947            return false;
948        }
949        if (roadEngineBox.getItemCount() == 1) {
950            log.debug("No locos available that match the model selected!");
951            JmriJOptionPane.showMessageDialog(this,
952                    Bundle.getMessage("NoLocosModel", model),
953                    Bundle.getMessage("TrainWillNotBuild", _train.getName()),
954                    JmriJOptionPane.WARNING_MESSAGE);
955        }
956        return true;
957    }
958
959    private boolean checkCabooseRoad(JComboBox<String> roadCabooseBox, JRadioButton cabooseRadioButton) {
960        String road = (String) roadCabooseBox.getSelectedItem();
961        if (!road.equals(NONE) && cabooseRadioButton.isSelected() && !_train.isCabooseRoadNameAccepted(road)) {
962            JmriJOptionPane.showMessageDialog(this,
963                    Bundle.getMessage("TrainNotCabooseRoad", _train.getName(), road),
964                    Bundle.getMessage("TrainWillNotBuild", _train.getName()),
965                    JmriJOptionPane.WARNING_MESSAGE);
966            return false;
967        }
968        return true;
969    }
970
971    private void enableButtons(boolean enabled) {
972        ownerNameAll.setEnabled(enabled);
973        ownerNameInclude.setEnabled(enabled);
974        ownerNameExclude.setEnabled(enabled);
975
976        builtDateAll.setEnabled(enabled);
977        builtDateAfter.setEnabled(enabled);
978        builtDateBefore.setEnabled(enabled);
979        builtDateRange.setEnabled(enabled);
980
981        none1.setEnabled(enabled);
982        change1Engine.setEnabled(enabled);
983        add1Engine.setEnabled(enabled);
984        remove1Engine.setEnabled(enabled);
985        modify1Caboose.setEnabled(enabled);
986        helper1Service.setEnabled(enabled);
987
988        none2.setEnabled(enabled);
989        change2Engine.setEnabled(enabled);
990        add2Engine.setEnabled(enabled);
991        remove2Engine.setEnabled(enabled);
992        modify2Caboose.setEnabled(enabled);
993        helper2Service.setEnabled(enabled);
994
995        saveTrainButton.setEnabled(enabled);
996    }
997
998    private void updateModelComboBoxes() {
999        InstanceManager.getDefault(EngineModels.class).updateComboBox(modelEngine1Box);
1000        InstanceManager.getDefault(EngineModels.class).updateComboBox(modelEngine2Box);
1001        modelEngine1Box.insertItemAt("", 0);
1002        modelEngine2Box.insertItemAt("", 0);
1003        if (_train != null) {
1004            modelEngine1Box.setSelectedItem(_train.getSecondLegEngineModel());
1005            modelEngine2Box.setSelectedItem(_train.getThirdLegEngineModel());
1006        }
1007    }
1008
1009    private void updateOwnerComboBoxes() {
1010        InstanceManager.getDefault(CarOwners.class).updateComboBox(ownerBox);
1011    }
1012
1013    // update caboose road box based on radio selection
1014    private void updateCabooseRoadComboBox(JComboBox<String> box) {
1015        box.removeAllItems();
1016        box.addItem(NONE);
1017        List<String> roads = InstanceManager.getDefault(CarManager.class).getCabooseRoadNames();
1018        for (String road : roads) {
1019            box.addItem(road);
1020        }
1021    }
1022
1023    private void updateEngineRoadComboBox(JComboBox<String> box, String engineModel) {
1024        if (engineModel == null) {
1025            return;
1026        }
1027        InstanceManager.getDefault(EngineManager.class).updateEngineRoadComboBox(engineModel, box);
1028    }
1029
1030    private void updateReturnToStagingCheckbox() {
1031        if (_train != null &&
1032                _train.getTrainDepartsRouteLocation() != null &&
1033                _train.getTrainTerminatesRouteLocation() != null &&
1034                _train.getTrainTerminatesRouteLocation().getLocation() != null &&
1035                _train.getTrainTerminatesRouteLocation().getLocation().isStaging() &&
1036                _train.getTrainDepartsRouteLocation().getName().equals(
1037                        _train.getTrainTerminatesRouteLocation().getName())) {
1038            allowThroughCarsCheckBox.setEnabled(false);
1039            if (Setup.isStagingAllowReturnEnabled()) {
1040                returnStagingCheckBox.setEnabled(false);
1041                returnStagingCheckBox.setSelected(true);
1042                returnStagingCheckBox.setToolTipText(Bundle.getMessage("TipReturnToStaging"));
1043            } else {
1044                returnStagingCheckBox.setEnabled(true);
1045                returnStagingCheckBox.setSelected(_train.isAllowReturnToStagingEnabled());
1046                returnStagingCheckBox.setToolTipText(NONE);
1047            }
1048        }
1049    }
1050
1051    private void updateRemoveEnginesRadioButtons() {
1052        if (_train != null &&
1053                _train.getTrainDepartsRouteLocation() != null &&
1054                _train.getTrainDepartsRouteLocation().getLocation() != null &&
1055                _train.getTrainDepartsRouteLocation().getLocation().isStaging()) {
1056            remove1Engine.setEnabled(false);
1057            remove2Engine.setEnabled(false);
1058        }
1059    }
1060
1061    private void createEngine1Panel() {
1062        engine1Option.removeAll();
1063        addItem(engine1Option, new JLabel(Bundle.getMessage("ChangeEnginesAt")), 0, 0);
1064        addItem(engine1Option, routePickup1Box, 1, 0);
1065        addItem(engine1Option, new JLabel(Bundle.getMessage("Engines")), 2, 0);
1066        addItem(engine1Option, numEngines1Box, 3, 0);
1067        addItem(engine1Option, new JLabel(Bundle.getMessage("Model")), 4, 0);
1068        addItem(engine1Option, modelEngine1Box, 5, 0);
1069        addItem(engine1Option, new JLabel(Bundle.getMessage("Road")), 6, 0);
1070        addItem(engine1Option, roadEngine1Box, 7, 0);
1071    }
1072
1073    private void createEngine2Panel() {
1074        engine2Option.removeAll();
1075        addItem(engine2Option, new JLabel(Bundle.getMessage("ChangeEnginesAt")), 0, 0);
1076        addItem(engine2Option, routePickup2Box, 1, 0);
1077        addItem(engine2Option, new JLabel(Bundle.getMessage("Engines")), 2, 0);
1078        addItem(engine2Option, numEngines2Box, 3, 0);
1079        addItem(engine2Option, new JLabel(Bundle.getMessage("Model")), 4, 0);
1080        addItem(engine2Option, modelEngine2Box, 5, 0);
1081        addItem(engine2Option, new JLabel(Bundle.getMessage("Road")), 6, 0);
1082        addItem(engine2Option, roadEngine2Box, 7, 0);
1083    }
1084
1085    private void createCaboose1Panel(boolean withCombox) {
1086        engine1caboose.removeAll();
1087        addItem(engine1caboose, remove1Caboose, 2, 6);
1088        addItem(engine1caboose, change1Caboose, 4, 6);
1089        addItem(engine1caboose, new JLabel(Bundle.getMessage("Road")), 5, 6);
1090        addItem(engine1caboose, roadCaboose1Box, 6, 6);
1091        if (withCombox) {
1092            addItem(engine1caboose, new JLabel(Bundle.getMessage("ChangeEnginesAt")), 0, 6);
1093            addItem(engine1caboose, routePickup1Box, 1, 6);
1094        } else {
1095            addItem(engine1caboose, keep1Caboose, 3, 6);
1096        }
1097    }
1098
1099    private void createCaboose2Panel(boolean withCombox) {
1100        engine2caboose.removeAll();
1101        addItem(engine2caboose, remove2Caboose, 2, 6);
1102        addItem(engine2caboose, change2Caboose, 4, 6);
1103        addItem(engine2caboose, new JLabel(Bundle.getMessage("Road")), 5, 6);
1104        addItem(engine2caboose, roadCaboose2Box, 6, 6);
1105        if (withCombox) {
1106            addItem(engine2caboose, new JLabel(Bundle.getMessage("ChangeEnginesAt")), 0, 6);
1107            addItem(engine2caboose, routePickup2Box, 1, 6);
1108        } else {
1109            addItem(engine2caboose, keep2Caboose, 3, 6);
1110        }
1111    }
1112
1113    @Override
1114    public void dispose() {
1115        InstanceManager.getDefault(CarOwners.class).removePropertyChangeListener(this);
1116        InstanceManager.getDefault(EngineModels.class).removePropertyChangeListener(this);
1117        Setup.getDefault().removePropertyChangeListener(this);
1118        if (_train != null) {
1119            _train.removePropertyChangeListener(this);
1120        }
1121        super.dispose();
1122    }
1123
1124    @Override
1125    public void propertyChange(java.beans.PropertyChangeEvent e) {
1126        if (Control.SHOW_PROPERTY) {
1127            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
1128                    .getNewValue());
1129        }
1130        if (e.getPropertyName().equals(CarOwners.CAROWNERS_CHANGED_PROPERTY)) {
1131            updateOwnerComboBoxes();
1132            updateOwnerNames();
1133        }
1134        if (e.getPropertyName().equals(EngineModels.ENGINEMODELS_CHANGED_PROPERTY) ||
1135                e.getPropertyName().equals(Train.TYPES_CHANGED_PROPERTY)) {
1136            updateModelComboBoxes();
1137        }
1138        if (e.getPropertyName().equals(Train.TRAIN_REQUIREMENTS_CHANGED_PROPERTY)) {
1139            updateTrainRequires1Option();
1140            updateTrainRequires2Option();
1141        }
1142        if (e.getPropertyName().equals(Setup.ALLOW_CARS_TO_RETURN_PROPERTY_CHANGE)) {
1143            updateReturnToStagingCheckbox();
1144        }
1145    }
1146
1147    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainEditBuildOptionsFrame.class);
1148}