001package jmri.jmrit.operations.trains;
002
003import java.awt.Color;
004import java.awt.Dimension;
005import java.util.List;
006import java.util.ResourceBundle;
007
008import javax.swing.*;
009
010import jmri.InstanceManager;
011import jmri.jmrit.operations.OperationsFrame;
012import jmri.jmrit.operations.OperationsXml;
013import jmri.jmrit.operations.automation.AutomationsTableFrameAction;
014import jmri.jmrit.operations.locations.Location;
015import jmri.jmrit.operations.locations.LocationManager;
016import jmri.jmrit.operations.rollingstock.cars.CarManagerXml;
017import jmri.jmrit.operations.rollingstock.engines.EngineManagerXml;
018import jmri.jmrit.operations.setup.*;
019import jmri.jmrit.operations.trains.excel.SetupExcelProgramFrameAction;
020import jmri.jmrit.operations.trains.excel.TrainCustomManifest;
021import jmri.jmrit.operations.trains.schedules.*;
022import jmri.jmrit.operations.trains.tools.*;
023import jmri.swing.JTablePersistenceManager;
024import jmri.util.swing.JmriJOptionPane;
025
026/**
027 * Frame for adding and editing the train roster for operations.
028 *
029 * @author Bob Jacobsen Copyright (C) 2001
030 * @author Daniel Boudreau Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013,
031 *         2014
032 */
033public class TrainsTableFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
034
035    public static final String MOVE = Bundle.getMessage("Move");
036    public static final String TERMINATE = Bundle.getMessage("Terminate");
037    public static final String RESET = Bundle.getMessage("Reset");
038    public static final String CONDUCTOR = Bundle.getMessage("Conductor");
039
040    CarManagerXml carManagerXml = InstanceManager.getDefault(CarManagerXml.class); // load cars
041    EngineManagerXml engineManagerXml = InstanceManager.getDefault(EngineManagerXml.class); // load engines
042    TrainManager trainManager = InstanceManager.getDefault(TrainManager.class);
043    TrainManagerXml trainManagerXml = InstanceManager.getDefault(TrainManagerXml.class);
044    LocationManager locationManager = InstanceManager.getDefault(LocationManager.class);
045
046    public TrainsTableModel trainsModel;
047    JTable trainsTable;
048    JScrollPane trainsPane;
049
050    // labels
051    JLabel numTrains = new JLabel();
052    JLabel textTrains = new JLabel(Bundle.getMessage("trains"));
053    JLabel textSep1 = new JLabel("      ");
054
055    // radio buttons
056    JRadioButton showTime = new JRadioButton(Bundle.getMessage("Time"));
057    JRadioButton showId = new JRadioButton(Bundle.getMessage("Id"));
058
059    JRadioButton moveRB = new JRadioButton(MOVE);
060    JRadioButton terminateRB = new JRadioButton(TERMINATE);
061    JRadioButton resetRB = new JRadioButton(RESET);
062    JRadioButton conductorRB = new JRadioButton(CONDUCTOR);
063
064    // major buttons
065    JButton addButton = new JButton(Bundle.getMessage("AddTrain"));
066    JButton buildButton = new JButton(Bundle.getMessage("Build"));
067    JButton printButton = new JButton(Bundle.getMessage("Print"));
068    JButton openFileButton = new JButton(Bundle.getMessage("OpenFile"));
069    JButton runFileButton = new JButton(Bundle.getMessage("RunFile"));
070    JButton switchListsButton = new JButton(Bundle.getMessage("SwitchLists"));
071    JButton terminateButton = new JButton(Bundle.getMessage("Terminate"));
072    JButton saveButton = new JButton(Bundle.getMessage("SaveBuilds"));
073
074    // check boxes
075    JCheckBox buildMsgBox = new JCheckBox(Bundle.getMessage("BuildMessages"));
076    JCheckBox buildReportBox = new JCheckBox(Bundle.getMessage("BuildReport"));
077    JCheckBox printPreviewBox = new JCheckBox(Bundle.getMessage("Preview"));
078    JCheckBox openFileBox = new JCheckBox(Bundle.getMessage("OpenFile"));
079    JCheckBox runFileBox = new JCheckBox(Bundle.getMessage("RunFile"));
080    public JCheckBox showAllBox = new JCheckBox(Bundle.getMessage("ShowAllTrains"));
081
082    public TrainsTableFrame() {
083        super();
084
085        updateTitle();
086
087        // create ShutDownTasks
088        createShutDownTask();
089        // always check for dirty operations files
090        setModifiedFlag(true);
091
092        // general GUI configuration
093        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
094
095        // Set up the jtable in a Scroll Pane..
096        trainsModel = new TrainsTableModel();
097        trainsTable = new JTable(trainsModel);
098        trainsPane = new JScrollPane(trainsTable);
099        trainsModel.initTable(trainsTable, this);
100
101        // Set up the control panel
102        // row 1
103        JPanel cp1 = new JPanel();
104        cp1.setLayout(new BoxLayout(cp1, BoxLayout.X_AXIS));
105
106        JPanel show = new JPanel();
107        show.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ShowClickToSort")));
108        show.add(showTime);
109        show.add(showId);
110
111        JPanel build = new JPanel();
112        build.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Build")));
113        build.add(showAllBox);
114
115        JPanel function = new JPanel();
116        function.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Function")));
117        function.add(printPreviewBox);
118        function.add(openFileBox);
119        function.add(runFileBox);
120
121        JPanel options = new JPanel();
122        options.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Options")));
123        options.add(buildMsgBox);
124        options.add(buildReportBox);
125
126        JPanel action = new JPanel();
127        action.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Action")));
128        action.add(moveRB);
129        action.add(conductorRB);
130        action.add(terminateRB);
131        action.add(resetRB);
132
133        cp1.add(show);
134        cp1.add(build);
135        cp1.add(function);
136        cp1.add(options);
137        cp1.add(action);
138
139        // tool tips, see setPrintButtonText() for more tool tips
140        addButton.setToolTipText(Bundle.getMessage("AddTrainTip"));
141        buildButton.setToolTipText(Bundle.getMessage("BuildSelectedTip"));
142        switchListsButton.setToolTipText(Bundle.getMessage("PreviewPrintSwitchListsTip"));
143
144        terminateButton.setToolTipText(Bundle.getMessage("TerminateSelectedTip"));
145        saveButton.setToolTipText(Bundle.getMessage("SaveBuildsTip"));
146        openFileButton.setToolTipText(Bundle.getMessage("OpenFileButtonTip"));
147        runFileButton.setToolTipText(Bundle.getMessage("RunFileButtonTip"));
148        buildMsgBox.setToolTipText(Bundle.getMessage("BuildMessagesTip"));
149        printPreviewBox.setToolTipText(Bundle.getMessage("PreviewTip"));
150        openFileBox.setToolTipText(Bundle.getMessage("OpenFileTip"));
151        runFileBox.setToolTipText(Bundle.getMessage("RunFileTip"));
152        showAllBox.setToolTipText(Bundle.getMessage("ShowAllTrainsTip"));
153
154        moveRB.setToolTipText(Bundle.getMessage("MoveTip"));
155        terminateRB.setToolTipText(Bundle.getMessage("TerminateTip"));
156        resetRB.setToolTipText(Bundle.getMessage("ResetTip"));
157
158        // row 2
159        JPanel addTrain = new JPanel();
160        addTrain.setBorder(BorderFactory.createTitledBorder(""));
161        addTrain.add(numTrains);
162        addTrain.add(textTrains);
163        addTrain.add(textSep1);
164        addTrain.add(addButton);
165
166        numTrains.setText(Integer.toString(trainManager.getNumEntries()));
167
168        JPanel select = new JPanel();
169        select.setBorder(BorderFactory.createTitledBorder(""));
170        select.add(buildButton);
171        select.add(printButton);
172        select.add(openFileButton);
173        select.add(runFileButton);
174        select.add(switchListsButton);
175        select.add(terminateButton);
176
177        JPanel save = new JPanel();
178        save.setBorder(BorderFactory.createTitledBorder(""));
179        save.add(saveButton);
180
181        JPanel cp2 = new JPanel();
182        cp2.setLayout(new BoxLayout(cp2, BoxLayout.X_AXIS));
183        cp2.add(addTrain);
184        cp2.add(select);
185        cp2.add(save);
186
187        // place controls in scroll pane
188        JPanel controlPanel = new JPanel();
189        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
190        controlPanel.add(cp1);
191        controlPanel.add(cp2);
192
193        JScrollPane controlPane = new JScrollPane(controlPanel);
194
195        getContentPane().add(trainsPane);
196        getContentPane().add(controlPane);
197
198        // setup buttons
199        addButtonAction(addButton);
200        addButtonAction(buildButton);
201        addButtonAction(printButton);
202        addButtonAction(openFileButton);
203        addButtonAction(runFileButton);
204        addButtonAction(switchListsButton);
205        addButtonAction(terminateButton);
206        addButtonAction(saveButton);
207
208        ButtonGroup showGroup = new ButtonGroup();
209        showGroup.add(showTime);
210        showGroup.add(showId);
211        showTime.setSelected(true);
212
213        ButtonGroup actionGroup = new ButtonGroup();
214        actionGroup.add(moveRB);
215        actionGroup.add(conductorRB);
216        actionGroup.add(terminateRB);
217        actionGroup.add(resetRB);
218
219        addRadioButtonAction(showTime);
220        addRadioButtonAction(showId);
221
222        addRadioButtonAction(moveRB);
223        addRadioButtonAction(terminateRB);
224        addRadioButtonAction(resetRB);
225        addRadioButtonAction(conductorRB);
226
227        buildMsgBox.setSelected(trainManager.isBuildMessagesEnabled());
228        buildReportBox.setSelected(trainManager.isBuildReportEnabled());
229        printPreviewBox.setSelected(trainManager.isPrintPreviewEnabled());
230        openFileBox.setSelected(trainManager.isOpenFileEnabled());
231        runFileBox.setSelected(trainManager.isRunFileEnabled());
232        showAllBox.setSelected(trainsModel.isShowAll());
233
234        // show open files only if create csv is enabled
235        updateRunAndOpenButtons();
236
237        addCheckBoxAction(buildMsgBox);
238        addCheckBoxAction(buildReportBox);
239        addCheckBoxAction(printPreviewBox);
240        addCheckBoxAction(showAllBox);
241        addCheckBoxAction(openFileBox);
242        addCheckBoxAction(runFileBox);
243
244        // Set the button text to Print or Preview
245        setPrintButtonText();
246        // Set the train action button text to Move or Terminate
247        setTrainActionButton();
248
249        // build menu
250        JMenuBar menuBar = new JMenuBar();
251        JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
252        toolMenu.add(new OptionAction());
253        toolMenu.add(new PrintOptionAction());
254        toolMenu.add(new BuildReportOptionAction());
255        toolMenu.addSeparator();
256        toolMenu.add(new TrainsByCarTypeAction());
257        toolMenu.add(new ChangeDepartureTimesAction());
258        toolMenu.add(new TrainsScheduleAction());
259        toolMenu.add(new TrainsTableSetColorAction());
260        toolMenu.add(new TrainCopyAction());
261        toolMenu.addSeparator();
262        toolMenu.add(new TrainsScriptAction(this));
263        toolMenu.add(new AutomationsTableFrameAction());
264        toolMenu.add(new SetupExcelProgramFrameAction());
265        toolMenu.addSeparator();
266        toolMenu.add(new ExportTrainRosterAction());
267        toolMenu.add(new ExportTimetableAction());
268        toolMenu.add(new ExportTrainLineupsAction());
269        toolMenu.addSeparator();
270        toolMenu.add(new TrainByCarTypeAction(null));
271        toolMenu.addSeparator();
272        toolMenu.add(new PrintTrainsAction(false, this));
273        toolMenu.add(new PrintTrainsAction(true, this));
274        toolMenu.add(new PrintSavedTrainManifestAction(false, null));
275        toolMenu.add(new PrintSavedTrainManifestAction(true, null));
276
277        menuBar.add(toolMenu);
278        menuBar.add(new jmri.jmrit.operations.OperationsMenu());
279        setJMenuBar(menuBar);
280
281        // add help menu to window
282        addHelpMenu("package.jmri.jmrit.operations.Operations_Trains", true); // NOI18N
283
284        initMinimumSize(new Dimension(Control.panelWidth700, Control.panelHeight250));
285
286        addHorizontalScrollBarKludgeFix(controlPane, controlPanel);
287
288        // listen for train schedule changes
289        InstanceManager.getDefault(TrainScheduleManager.class).addPropertyChangeListener(this);
290        // listen for changes in the number of trains
291        trainManager.addPropertyChangeListener(this);
292        Setup.getDefault().addPropertyChangeListener(this);
293        // listen for location switch list changes
294        addPropertyChangeLocations();
295
296        // auto save
297        AutoSave.start();
298    }
299
300    @Override
301    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
302        log.debug("radio button activated");
303        // clear any sorts by column
304        clearTableSort(trainsTable);
305        if (ae.getSource() == showId) {
306            trainsModel.setSort(trainsModel.SORTBYID);
307        }
308        if (ae.getSource() == showTime) {
309            trainsModel.setSort(trainsModel.SORTBYTIME);
310        }
311        if (ae.getSource() == moveRB) {
312            trainManager.setTrainsFrameTrainAction(MOVE);
313        }
314        if (ae.getSource() == terminateRB) {
315            trainManager.setTrainsFrameTrainAction(TERMINATE);
316        }
317        if (ae.getSource() == resetRB) {
318            trainManager.setTrainsFrameTrainAction(RESET);
319        }
320        if (ae.getSource() == conductorRB) {
321            trainManager.setTrainsFrameTrainAction(CONDUCTOR);
322        }
323    }
324
325    TrainSwitchListEditFrame tslef;
326
327    // add, build, print, switch lists, terminate, and save buttons
328    @Override
329    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
330        // log.debug("train button activated");
331        if (ae.getSource() == addButton) {
332            new TrainEditFrame(null);
333        }
334        if (ae.getSource() == buildButton) {
335            runFileButton.setEnabled(false);
336            // uses a thread which allows table updates during build
337            trainManager.buildSelectedTrains(getSortByList());
338        }
339        if (ae.getSource() == printButton) {
340            trainManager.printSelectedTrains(getSortByList());
341        }
342        if (ae.getSource() == openFileButton) {
343            // open the csv files
344            List<Train> trains = getSortByList();
345            for (Train train : trains) {
346                if (train.isBuildEnabled()) {
347                    if (!train.isBuilt() && trainManager.isBuildMessagesEnabled()) {
348                        int response = JmriJOptionPane.showConfirmDialog(this,
349                                Bundle.getMessage("NeedToBuildBeforeOpenFile",
350                                        train.getName()),
351                                Bundle.getMessage("ErrorTitle"), JmriJOptionPane.OK_CANCEL_OPTION);
352                        if (response != JmriJOptionPane.OK_OPTION ) {
353                            break;
354                        }
355                    } else if (train.isBuilt()) {
356                        train.openFile();
357                    }
358                }
359            }
360        }
361        if (ae.getSource() == runFileButton) {
362            // Processes the CSV Manifest files using an external custom program.
363            TrainCustomManifest tcm = InstanceManager.getDefault(TrainCustomManifest.class);
364            if (!tcm.excelFileExists()) {
365                log.warn("Manifest creator file not found!, directory path: {}, file name: {}", tcm.getDirectoryPathName(),
366                        tcm.getFileName());
367                JmriJOptionPane.showMessageDialog(this,
368                        Bundle.getMessage("LoadDirectoryNameFileName",
369                                tcm.getDirectoryPathName(), tcm.getFileName()),
370                        Bundle.getMessage("ManifestCreatorNotFound"), JmriJOptionPane.ERROR_MESSAGE);
371                return;
372            }
373            List<Train> trains = getSortByList();
374            for (Train train : trains) {
375                if (train.isBuildEnabled()) {
376                    if (!train.isBuilt() && trainManager.isBuildMessagesEnabled()) {
377                        int response = JmriJOptionPane.showConfirmDialog(this,
378                                Bundle.getMessage("NeedToBuildBeforeRunFile",
379                                        train.getName()),
380                                Bundle.getMessage("ErrorTitle"), JmriJOptionPane.OK_CANCEL_OPTION);
381                        if (response != JmriJOptionPane.OK_OPTION ) {
382                            break;
383                        }
384                    } else if (train.isBuilt()) {
385                        // Add csv manifest file to our collection to be processed.
386                        tcm.addCsvFile(train.createCsvManifestFile());
387                        train.setPrinted(true);
388                    }
389                }
390            }
391            // Now run the user specified custom Manifest processor program
392            tcm.process();
393        }
394        if (ae.getSource() == switchListsButton) {
395            if (tslef != null) {
396                tslef.dispose();
397            }
398            tslef = new TrainSwitchListEditFrame();
399            tslef.initComponents();
400        }
401        if (ae.getSource() == terminateButton) {
402            trainManager.terminateSelectedTrains(getSortByList());
403        }
404        if (ae.getSource() == saveButton) {
405            storeValues();
406        }
407    }
408
409    SortOrder _status = SortOrder.ASCENDING;
410
411    public String getSortBy() {
412        // set the defaults
413        String sortBy = TrainsTableModel.TIMECOLUMNNAME;
414        _status = SortOrder.ASCENDING;
415        // now look to see if a sort is active
416        for (RowSorter.SortKey key : trainsTable.getRowSorter().getSortKeys()) {
417            String name = trainsModel.getColumnName(key.getColumn());
418            SortOrder status = key.getSortOrder();
419            // log.debug("Column {} status {}", name, status);
420            if (!status.equals(SortOrder.UNSORTED) && !name.isEmpty()) {
421                sortBy = name;
422                _status = status;
423                break;
424            }
425        }
426        return sortBy;
427    }
428
429    public List<Train> getSortByList() {
430        return getSortByList(getSortBy());
431    }
432
433    public List<Train> getSortByList(String sortBy) {
434        List<Train> sysList;
435
436        if (sortBy.equals(TrainsTableModel.IDCOLUMNNAME)) {
437            sysList = trainManager.getTrainsByIdList();
438        } else if (sortBy.equals(TrainsTableModel.TIMECOLUMNNAME)) {
439            sysList = trainManager.getTrainsByTimeList();
440        } else if (sortBy.equals(TrainsTableModel.DEPARTSCOLUMNNAME)) {
441            sysList = trainManager.getTrainsByDepartureList();
442        } else if (sortBy.equals(TrainsTableModel.TERMINATESCOLUMNNAME)) {
443            sysList = trainManager.getTrainsByTerminatesList();
444        } else if (sortBy.equals(TrainsTableModel.ROUTECOLUMNNAME)) {
445            sysList = trainManager.getTrainsByRouteList();
446        } else if (sortBy.equals(TrainsTableModel.STATUSCOLUMNNAME)) {
447            sysList = trainManager.getTrainsByStatusList();
448        } else if (sortBy.equals(TrainsTableModel.DESCRIPTIONCOLUMNNAME)) {
449            sysList = trainManager.getTrainsByDescriptionList();
450        } else {
451            sysList = trainManager.getTrainsByNameList();
452        }
453        return sysList;
454    }
455
456    // Modifies button text and tool tips
457    private void setPrintButtonText() {
458        if (printPreviewBox.isSelected()) {
459            printButton.setText(Bundle.getMessage("Preview"));
460            printButton.setToolTipText(Bundle.getMessage("PreviewSelectedTip"));
461            buildReportBox.setToolTipText(Bundle.getMessage("BuildReportPreviewTip"));
462        } else {
463            printButton.setText(Bundle.getMessage("Print"));
464            printButton.setToolTipText(Bundle.getMessage("PrintSelectedTip"));
465            buildReportBox.setToolTipText(Bundle.getMessage("BuildReportPrintTip"));
466        }
467    }
468
469    private void setTrainActionButton() {
470        moveRB.setSelected(trainManager.getTrainsFrameTrainAction().equals(TrainsTableFrame.MOVE));
471        terminateRB.setSelected(trainManager.getTrainsFrameTrainAction().equals(TrainsTableFrame.TERMINATE));
472        resetRB.setSelected(trainManager.getTrainsFrameTrainAction().equals(TrainsTableFrame.RESET));
473        conductorRB.setSelected(trainManager.getTrainsFrameTrainAction().equals(TrainsTableFrame.CONDUCTOR));
474    }
475
476    @Override
477    public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) {
478        if (ae.getSource() == buildMsgBox) {
479            trainManager.setBuildMessagesEnabled(buildMsgBox.isSelected());
480        }
481        if (ae.getSource() == buildReportBox) {
482            trainManager.setBuildReportEnabled(buildReportBox.isSelected());
483        }
484        if (ae.getSource() == printPreviewBox) {
485            trainManager.setPrintPreviewEnabled(printPreviewBox.isSelected());
486            setPrintButtonText(); // set the button text for Print or Preview
487        }
488        if (ae.getSource() == openFileBox) {
489            trainManager.setOpenFileEnabled(openFileBox.isSelected());
490            runFileBox.setSelected(false);
491            trainManager.setRunFileEnabled(false);
492        }
493        if (ae.getSource() == runFileBox) {
494            trainManager.setRunFileEnabled(runFileBox.isSelected());
495            openFileBox.setSelected(false);
496            trainManager.setOpenFileEnabled(false);
497        }
498        if (ae.getSource() == showAllBox) {
499            trainsModel.setShowAll(showAllBox.isSelected());
500        }
501    }
502
503    private void updateTitle() {
504        String title = Bundle.getMessage("TitleTrainsTable");
505        TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class).getActiveSchedule();
506        if (sch != null) {
507            title = title + " (" + sch.getName() + ")";
508        }
509        setTitle(title);
510    }
511
512    private void updateSwitchListButton() {
513        List<Location> locations = locationManager.getList();
514        for (Location location : locations) {
515            if (location != null && location.isSwitchListEnabled() && location.getStatus().equals(Location.MODIFIED)) {
516                switchListsButton.setBackground(Color.RED);
517                return;
518            }
519        }
520        switchListsButton.setBackground(Color.GREEN);
521    }
522
523    // show open files only if create csv is enabled
524    private void updateRunAndOpenButtons() {
525        openFileBox.setVisible(Setup.isGenerateCsvManifestEnabled());
526        openFileButton.setVisible(Setup.isGenerateCsvManifestEnabled());
527        runFileBox.setVisible(Setup.isGenerateCsvManifestEnabled());
528        runFileButton.setVisible(Setup.isGenerateCsvManifestEnabled());
529    }
530
531    private synchronized void addPropertyChangeLocations() {
532        List<Location> locations = locationManager.getList();
533        for (Location location : locations) {
534            location.addPropertyChangeListener(this);
535        }
536    }
537
538    private synchronized void removePropertyChangeLocations() {
539        List<Location> locations = locationManager.getList();
540        for (Location location : locations) {
541            location.removePropertyChangeListener(this);
542        }
543    }
544
545    @Override
546    public void dispose() {
547        trainsModel.dispose();
548        trainManager.runShutDownScripts();
549        trainManager.removePropertyChangeListener(this);
550        InstanceManager.getDefault(TrainScheduleManager.class).removePropertyChangeListener(this);
551        Setup.getDefault().removePropertyChangeListener(this);
552        removePropertyChangeLocations();
553        setModifiedFlag(false);
554        InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> {
555            tpm.stopPersisting(trainsTable);
556        });
557        super.dispose();
558    }
559
560    @Override
561    protected void handleModified() {
562        if (!getModifiedFlag()) {
563            return;
564        }
565        if (Setup.isAutoSaveEnabled()) {
566            storeValues();
567            return;
568        }
569        if (OperationsXml.areFilesDirty()) {
570            int result = JmriJOptionPane.showOptionDialog(this, Bundle.getMessage("PromptQuitWindowNotWritten"),
571                    Bundle.getMessage("PromptSaveQuit"), JmriJOptionPane.YES_NO_OPTION,
572                    JmriJOptionPane.WARNING_MESSAGE, null,
573                    new String[] { ResourceBundle.getBundle("jmri.util.UtilBundle").getString("WarnYesSave"), // NOI18N
574                            ResourceBundle.getBundle("jmri.util.UtilBundle").getString("WarnNoClose") }, // NOI18N
575                    ResourceBundle.getBundle("jmri.util.UtilBundle").getString("WarnYesSave"));
576            if (result == JmriJOptionPane.YES_OPTION) {
577                // user wants to save
578                storeValues();
579            }
580        }
581    }
582
583    @Override
584    protected void storeValues() {
585        super.storeValues();
586    }
587
588    @Override
589    public void propertyChange(java.beans.PropertyChangeEvent e) {
590        if (Control.SHOW_PROPERTY) {
591            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(),
592                    e.getNewValue());
593        }
594        if (e.getPropertyName().equals(TrainScheduleManager.SCHEDULE_ID_CHANGED_PROPERTY)) {
595            updateTitle();
596        }
597        if (e.getPropertyName().equals(Location.STATUS_CHANGED_PROPERTY) ||
598                e.getPropertyName().equals(Location.SWITCHLIST_CHANGED_PROPERTY)) {
599            log.debug("update switch list button location ({})", e.getSource());
600            updateSwitchListButton();
601        }
602        if (e.getPropertyName().equals(Setup.MANIFEST_CSV_PROPERTY_CHANGE)) {
603            updateRunAndOpenButtons();
604        }
605        if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY)) {
606            numTrains.setText(Integer.toString(trainManager.getNumEntries()));
607        }
608        if (e.getPropertyName().equals(TrainManager.TRAINS_BUILT_CHANGED_PROPERTY)) {
609            runFileButton.setEnabled(true);
610        }
611    }
612
613    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainsTableFrame.class);
614}