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