001package jmri.jmrit.consisttool;
002
003import java.awt.FlowLayout;
004import java.awt.event.ActionEvent;
005import java.awt.event.KeyEvent;
006import java.awt.event.KeyListener;
007import java.beans.PropertyChangeEvent;
008import java.io.IOException;
009import java.util.List;
010import java.util.ArrayList;
011import javax.swing.*;
012
013import jmri.Consist;
014import jmri.ConsistListListener;
015import jmri.ConsistListener;
016import jmri.ConsistManager;
017import jmri.LocoAddress;
018import jmri.DccLocoAddress;
019import jmri.InstanceManager;
020import jmri.jmrit.DccLocoAddressSelector;
021import jmri.jmrit.roster.swing.GlobalRosterEntryComboBox;
022import jmri.jmrit.roster.swing.RosterEntryComboBox;
023import jmri.jmrit.roster.Roster;
024import jmri.jmrit.roster.RosterEntry;
025import jmri.jmrit.symbolicprog.CvTableModel;
026import jmri.jmrit.symbolicprog.CvValue;
027import jmri.jmrit.throttle.ThrottleFrame;
028import jmri.jmrit.throttle.ThrottleFrameManager;
029import jmri.util.JmriJFrame;
030import jmri.util.gui.GuiLafPreferencesManager;
031import jmri.util.swing.JmriJOptionPane;
032
033import org.jdom2.JDOMException;
034
035/**
036 * Frame object for manipulating consists.
037 *
038 * @author Paul Bender Copyright (C) 2003-2008
039 */
040public class ConsistToolFrame extends JmriJFrame implements ConsistListener, ConsistListListener {
041
042    // GUI member declarations
043    JLabel textAdrLabel = new JLabel();
044    DccLocoAddressSelector adrSelector = new DccLocoAddressSelector();
045    ConsistComboBox consistComboBox = new ConsistComboBox();
046    JRadioButton isAdvancedConsist = new JRadioButton(Bundle.getMessage("AdvancedConsistButtonText"));
047    JRadioButton isCSConsist = new JRadioButton(Bundle.getMessage("CommandStationConsistButtonText"));
048    JButton deleteButton = new JButton();
049    JButton throttleButton = new JButton();
050    JButton reverseButton = new JButton();
051    JButton restoreButton = new JButton();
052    JLabel textLocoLabel = new JLabel();
053    DccLocoAddressSelector locoSelector = new DccLocoAddressSelector();
054    RosterEntryComboBox locoRosterBox;
055    JButton addLocoButton = new JButton();
056    JButton resetLocoButton = new JButton();
057    JCheckBox locoDirectionNormal = new JCheckBox(Bundle.getMessage("DirectionNormalText"));
058    ConsistDataModel consistModel = new ConsistDataModel();
059    JTable consistTable = new JTable(consistModel);
060    ConsistManager consistManager = null;
061    JLabel _status = new JLabel(Bundle.getMessage("DefaultStatusText"));
062    private int _Consist_Type = Consist.ADVANCED_CONSIST;
063    private ConsistFile consistFile = null;
064
065    public ConsistToolFrame() {
066        super();
067        init();
068    }
069
070    private void init() {
071        consistManager = InstanceManager.getDefault(jmri.ConsistManager.class);
072
073        consistFile = new ConsistFile();
074        try {
075            consistFile.readFile();
076        } catch (IOException | JDOMException e) {
077            log.warn("error reading consist file: {}", e.getMessage());
078        }
079
080        // register to be notified if the consist list changes.
081        consistManager.addConsistListListener(this);
082
083        // request an update from the layout.
084        consistManager.requestUpdateFromLayout();
085
086        // configure items for GUI
087        textAdrLabel.setText(Bundle.getMessage("AddressLabelText"));
088        textAdrLabel.setVisible(true);
089
090        adrSelector.setVisible(true);
091        adrSelector.setToolTipText(Bundle.getMessage("AddressSelectorToolTip"));
092        textAdrLabel.setLabelFor(adrSelector);
093
094        initializeConsistBox();
095
096        consistComboBox.addActionListener((ActionEvent e) -> consistSelected());
097
098        isAdvancedConsist.setSelected(true);
099        isAdvancedConsist.setVisible(true);
100        isAdvancedConsist.setEnabled(false);
101        isAdvancedConsist.addActionListener((ActionEvent e) -> {
102            isAdvancedConsist.setSelected(true);
103            isCSConsist.setSelected(false);
104            _Consist_Type = Consist.ADVANCED_CONSIST;
105            adrSelector.setEnabled(true);
106        });
107        isCSConsist.setSelected(false);
108        isCSConsist.setVisible(true);
109        isCSConsist.setEnabled(false);
110        isCSConsist.addActionListener((ActionEvent e) -> {
111            isAdvancedConsist.setSelected(false);
112            isCSConsist.setSelected(true);
113            _Consist_Type = Consist.CS_CONSIST;
114            adrSelector.setEnabled((consistManager.csConsistNeedsSeperateAddress()));
115        });
116
117        if (consistManager.isCommandStationConsistPossible()) {
118            isAdvancedConsist.setEnabled(true);
119            isCSConsist.setEnabled(true);
120        }
121
122        deleteButton.setText(Bundle.getMessage("ButtonDelete"));
123        deleteButton.setVisible(true);
124        deleteButton.setToolTipText(Bundle.getMessage("DeleteButtonToolTip"));
125        deleteButton.addActionListener(this::deleteButtonActionPerformed);
126
127        throttleButton.setText(Bundle.getMessage("ThrottleButtonText"));
128        throttleButton.setVisible(true);
129        throttleButton.setToolTipText(Bundle.getMessage("ThrottleButtonToolTip"));
130        throttleButton.addActionListener(this::throttleButtonActionPerformed);
131
132        reverseButton.setText(Bundle.getMessage("ReverseButtonText"));
133        reverseButton.setVisible(true);
134        reverseButton.setToolTipText(Bundle.getMessage("ReverseButtonToolTip"));
135        reverseButton.addActionListener(this::reverseButtonActionPerformed);
136
137        restoreButton.setText(Bundle.getMessage("RestoreButtonText"));
138        restoreButton.setVisible(true);
139        restoreButton.setToolTipText(Bundle.getMessage("RestoreButtonToolTip"));
140        restoreButton.addActionListener(this::restoreButtonActionPerformed);
141
142        // Set up the controls for the First Locomotive in the consist.
143        textLocoLabel.setText(Bundle.getMessage("LocoLabelText"));
144        textLocoLabel.setVisible(true);
145
146        locoSelector.setToolTipText(Bundle.getMessage("LocoSelectorToolTip"));
147        locoSelector.setVisible(true);
148        textLocoLabel.setLabelFor(locoSelector);
149
150        locoSelector.addKeyListener(new KeyListener() {
151            @Override
152            public void keyPressed(KeyEvent e) {
153                // if we start typing, set the selected index of the locoRosterbox to nothing.
154                locoRosterBox.setSelectedIndex(0);
155            }
156
157            @Override
158            public void keyTyped(KeyEvent e) {
159                // only handling key presses
160            }
161
162            @Override
163            public void keyReleased(KeyEvent e) {
164                // only handling key presses
165            }
166        });
167
168        locoRosterBox = new GlobalRosterEntryComboBox();
169        locoRosterBox.setNonSelectedItem("");
170        locoRosterBox.setSelectedIndex(0);
171
172        locoRosterBox.addPropertyChangeListener("selectedRosterEntries", (PropertyChangeEvent pce) -> locoSelected());
173
174        locoRosterBox.setVisible(true);
175
176        locoDirectionNormal.setToolTipText(Bundle.getMessage("DirectionNormalToolTip"));
177
178        locoDirectionNormal.setSelected(true);
179        locoDirectionNormal.setVisible(true);
180        locoDirectionNormal.setEnabled(false);
181
182        addLocoButton.setText(Bundle.getMessage("ButtonAddText"));
183        addLocoButton.setVisible(true);
184        addLocoButton.setToolTipText(Bundle.getMessage("AddButtonToolTip"));
185        addLocoButton.addActionListener(this::addLocoButtonActionPerformed);
186
187        resetLocoButton.setText(Bundle.getMessage("ButtonReset"));
188        resetLocoButton.setVisible(true);
189        resetLocoButton.setToolTipText(Bundle.getMessage("ResetButtonToolTip"));
190        resetLocoButton.addActionListener(this::resetLocoButtonActionPerformed);
191
192        // general GUI config
193        setTitle(Bundle.getMessage("ConsistToolTitle"));
194        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
195
196        JMenuBar menuBar = new JMenuBar();
197        setJMenuBar(menuBar);
198
199        // add a "File" menu
200        JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile"));
201        menuBar.add(fileMenu);
202
203        // Add a save item
204        fileMenu.add(new AbstractAction(Bundle.getMessage("ScanConsists")) {
205            @Override
206            public void actionPerformed(ActionEvent e) {
207                scanRoster();
208                initializeConsistBox();
209                consistModel.fireTableDataChanged();
210                resetLocoButtonActionPerformed(e);
211            }
212        });
213
214        // install items in GUI
215        // The address and related buttons are installed in a single pane
216        JPanel addressPanel = new JPanel();
217        addressPanel.setLayout(new FlowLayout());
218
219        addressPanel.add(textAdrLabel);
220        addressPanel.add(adrSelector.getCombinedJPanel());
221        addressPanel.add(consistComboBox);
222        addressPanel.add(isAdvancedConsist);
223        addressPanel.add(isCSConsist);
224
225        getContentPane().add(addressPanel);
226
227        // The address and related buttons for each Locomotive
228        // are installed in a single pane
229        // New Locomotive
230        JPanel locoPanel = new JPanel();
231        locoPanel.setLayout(new FlowLayout());
232
233        locoPanel.add(textLocoLabel);
234
235        locoPanel.add(locoSelector.getCombinedJPanel());
236
237        locoPanel.add(locoRosterBox);
238        locoPanel.add(locoDirectionNormal);
239
240        locoPanel.add(addLocoButton);
241        locoPanel.add(resetLocoButton);
242
243        getContentPane().add(locoPanel);
244
245        // setup the consist table
246        consistTable.setRowHeight(InstanceManager.getDefault(GuiLafPreferencesManager.class).getFontSize()*2 + 4);
247        // Set up the jtable in a Scroll Pane..
248        JScrollPane consistPane = new JScrollPane(consistTable);
249        consistPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
250        consistModel.initTable(consistTable);
251        getContentPane().add(consistPane);
252
253        // Set up the Control Button panel
254        JPanel controlPanel = new JPanel();
255        controlPanel.setLayout(new FlowLayout());
256
257        controlPanel.add(deleteButton);
258        controlPanel.add(throttleButton);
259        controlPanel.add(reverseButton);
260        controlPanel.add(restoreButton);
261
262        getContentPane().add(controlPanel);
263
264        // add the status line directly to the bottom of the ContentPane.
265        JPanel statusPanel = new JPanel();
266        statusPanel.setLayout(new FlowLayout());
267        statusPanel.add(_status);
268        getContentPane().add(statusPanel);
269
270        addHelpMenu("package.jmri.jmrit.consisttool.ConsistToolFrame", true);
271        pack();
272
273    }
274
275    private void initializeConsistBox() {
276        ArrayList<LocoAddress> existingConsists = consistManager.getConsistList();
277        if (!existingConsists.isEmpty()) {
278            java.util.Collections.sort(existingConsists, new jmri.util.LocoAddressComparator()); // sort the consist list.
279            if (adrSelector.getAddress() != null) {
280                if (consistModel.getConsist() != null) {
281                    consistModel.getConsist().removeConsistListener(this);
282                    setDefaultStatus();
283                }
284                consistModel.setConsist(adrSelector.getAddress());
285                consistModel.getConsist().addConsistListener(this);
286                adrSelector.setEnabled(false);
287            } else {
288                if (consistModel.getConsist() != null) {
289                    consistModel.getConsist().removeConsistListener(this);
290                    setDefaultStatus();
291                }
292                consistModel.setConsist((Consist) null);
293                adrSelector.setEnabled(true);
294            }
295        } else {
296            if (consistModel.getConsist() != null) {
297                consistModel.getConsist().removeConsistListener(this);
298                setDefaultStatus();
299            }
300            consistModel.setConsist((Consist) null);
301            adrSelector.setEnabled(true);
302        }
303    }
304
305    public void deleteButtonActionPerformed(ActionEvent e) {
306        if (adrSelector.getAddress() == null) {
307            reportNoConsistSeletected();
308            return;
309        }
310        DccLocoAddress address = adrSelector.getAddress();
311        consistManager.getConsist(address);
312        // confirm delete
313        if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("DeleteWarningDialog", address),
314                Bundle.getMessage("QuestionTitle"), JmriJOptionPane.YES_NO_OPTION,
315                JmriJOptionPane.QUESTION_MESSAGE) != JmriJOptionPane.YES_OPTION ) {
316            return; // do not delete
317        }
318        try {
319            adrSelector.reset();
320            consistManager.delConsist(address);
321        } catch (Exception ex) {
322            log.error("Error delting consist {}", address, ex);
323        }        
324        adrSelector.setEnabled(true);
325        initializeConsistBox();
326        resetLocoButtonActionPerformed(e);
327        canAdd();
328    }
329
330    public void throttleButtonActionPerformed(ActionEvent e) {
331        if (adrSelector.getAddress() == null) {
332            reportNoConsistSeletected();
333            return;
334        }
335        // make sure any new locomotives are added to the consist.
336        addLocoButtonActionPerformed(e);
337        // Create a throttle object with the
338        ThrottleFrame tf
339                = InstanceManager.getDefault(ThrottleFrameManager.class).createThrottleFrame();        
340
341        // Notify the throttle of the selected consist address
342        tf.getAddressPanel().setConsistAddress(adrSelector.getAddress());
343        tf.toFront();
344    }
345
346    public void reverseButtonActionPerformed(ActionEvent e) {
347        if (adrSelector.getAddress() == null) {
348            reportNoConsistSeletected();
349            return;
350        }
351        // make sure any new locomotives are added to the consist.
352        addLocoButtonActionPerformed(e);
353
354        /*
355         * get the array list of the locomotives in the consist
356         */
357        DccLocoAddress address = adrSelector.getAddress();
358        Consist tempConsist = consistManager.getConsist(address);
359        tempConsist.reverse();
360        consistManager.notifyConsistListChanged();
361    }
362
363    public void restoreButtonActionPerformed(ActionEvent e) {
364        if (adrSelector.getAddress() == null) {
365            reportNoConsistSeletected();
366            return;
367        }
368        // make sure any new locomotives are added to the consist.
369        addLocoButtonActionPerformed(e);
370
371        /*
372         * get the array list of the locomotives in the consist
373         */
374        DccLocoAddress address = adrSelector.getAddress();
375        Consist tempConsist = consistManager.getConsist(address);
376        tempConsist.restore();
377        consistManager.notifyConsistListChanged();
378    }
379
380    public void consistSelected() {
381        log.debug("Consist Selected");
382        if (consistComboBox.getSelectedIndex() == -1 && adrSelector.getAddress() != null) {
383            log.debug("No Consist Selected");
384            adrSelector.setEnabled(false);
385            recallConsist();
386        } else if (consistComboBox.getSelectedIndex() == -1
387                || consistComboBox.getSelectedItem().equals("") 
388                || consistComboBox.getSelectedItem().equals(Bundle.getMessage("NoConsistSelected"))) {
389            log.debug("Null Consist Selected");
390            adrSelector.reset();
391            adrSelector.setEnabled(true);
392            recallConsist();
393        } else if (((DccLocoAddress) consistComboBox.getSelectedItem()) != adrSelector.getAddress()) {
394            log.debug("Consist {} consistComboBox", consistComboBox.getSelectedItem());
395            adrSelector.setEnabled(false);
396            adrSelector.setAddress((DccLocoAddress) consistComboBox.getSelectedItem());
397            recallConsist();
398        }
399    }
400
401    // Recall the consist
402    private void recallConsist() {
403        if (adrSelector.getAddress() == null) {
404            // Clear any consist information that was present
405            locoSelector.reset();
406            locoRosterBox.setSelectedIndex(0);
407            if (consistModel.getConsist() != null) {
408                consistModel.getConsist().removeConsistListener(this);
409                setDefaultStatus();
410            }
411            consistModel.setConsist((Consist) null);
412
413            canAdd();
414
415            return;
416        }
417        DccLocoAddress address = adrSelector.getAddress();
418        if (consistModel.getConsist() != null) {
419            consistModel.getConsist().removeConsistListener(this);
420            _status.setText(Bundle.getMessage("DefaultStatusText"));
421            setDefaultStatus();
422        }
423        Consist selectedConsist = consistManager.getConsist(address);
424        consistModel.setConsist(selectedConsist);
425        selectedConsist.addConsistListener(this);
426
427        // reset the editable locomotive information.
428        locoSelector.reset();
429        locoRosterBox.setSelectedIndex(0);
430        locoDirectionNormal.setSelected(true);
431
432        // if there aren't any locomotives in the consist, don't let
433        // the user change the direction
434        locoDirectionNormal.setEnabled(consistModel.getRowCount()!=0);
435
436        log.debug("Recall Consist {}", address);
437
438        // What type of consist is this?
439        if (selectedConsist.getConsistType() == Consist.ADVANCED_CONSIST) {
440            log.debug("Consist type is Advanced Consist ");
441            isAdvancedConsist.setSelected(true);
442            isCSConsist.setSelected(false);
443            _Consist_Type = Consist.ADVANCED_CONSIST;
444        } else {
445            // This must be a CS Consist.
446            log.debug("Consist type is Command Station Consist ");
447            isAdvancedConsist.setSelected(false);
448            isCSConsist.setSelected(true);
449            _Consist_Type = Consist.CS_CONSIST;
450        }
451
452        canAdd();
453    }
454
455    public void resetLocoButtonActionPerformed(ActionEvent e) {
456        locoSelector.reset();
457        locoRosterBox.setSelectedIndex(0);
458        locoDirectionNormal.setSelected(true);
459        // if there aren't any locomotives in the consist, don't let
460        // the user change the direction
461        locoDirectionNormal.setEnabled(consistModel.getRowCount() != 0);
462    }
463
464    // Check to see if a consist address is selected, and if it
465    // is, dissable the "add button" if the maximum consist size is reached
466    public void canAdd() {
467        // If a consist address is selected, dissable the "add button"
468        // if the maximum size is reached
469        if (adrSelector.getAddress() != null) {
470            DccLocoAddress address = adrSelector.getAddress();
471            if (consistModel.getRowCount() == consistManager.getConsist(address).sizeLimit()) {
472                locoSelector.setEnabled(false);
473                locoRosterBox.setEnabled(false);
474                addLocoButton.setEnabled(false);
475                resetLocoButton.setEnabled(false);
476                locoDirectionNormal.setEnabled(false);
477            } else {
478                enableGuiControls();
479            }
480        } else {
481            enableGuiControls();
482        }
483    }
484
485    private void enableGuiControls(){
486        locoSelector.setEnabled(true);
487        locoRosterBox.setEnabled(true);
488        addLocoButton.setEnabled(true);
489        resetLocoButton.setEnabled(true);
490        locoDirectionNormal.setEnabled(false);
491        // if there aren't any locomotives in the consist, don't let
492        // the user change the direction
493        locoDirectionNormal.setEnabled(consistModel.getRowCount() != 0);
494    }
495
496    public void addLocoButtonActionPerformed(ActionEvent e) {
497        if (locoSelector.getAddress() == null) {
498            return;
499        }
500        if (_Consist_Type == Consist.ADVANCED_CONSIST && adrSelector.getAddress() == null) {
501            reportNoConsistSeletected();
502            return;
503        } else if (_Consist_Type == Consist.ADVANCED_CONSIST
504                && adrSelector.getAddress().isLongAddress()) {
505            JmriJOptionPane.showMessageDialog(this,
506                    Bundle.getMessage("RequiresShortConsistError"));
507            return;
508        } else if (_Consist_Type == Consist.CS_CONSIST && adrSelector.getAddress() == null) {
509            if (consistManager.csConsistNeedsSeperateAddress()) {
510                reportNoConsistSeletected();
511                return;
512            } else {
513                // We need to set an identifier so we can recall the
514                // consist.  We're going to use the lead locomotive number
515                // for this.
516                adrSelector.setAddress(locoSelector.getAddress());
517            }
518        }
519        DccLocoAddress address = adrSelector.getAddress();
520        /*
521         * Make sure the marked consist type matches the consist type stored for
522         * this consist
523         */
524        if (_Consist_Type != consistManager.getConsist(address).getConsistType()) {
525            if (log.isDebugEnabled()) {
526                if (_Consist_Type == Consist.ADVANCED_CONSIST) {
527                    log.debug("Setting Consist Type to Advanced Consist");
528                } else if (_Consist_Type == Consist.CS_CONSIST) {
529                    log.debug("Setting Consist Type to Command Station Assisted Consist");
530                }
531            }
532            consistManager.getConsist(address).setConsistType(_Consist_Type);
533        }
534
535        DccLocoAddress locoaddress = locoSelector.getAddress();
536
537        // Make sure the Address in question is allowed for this type of
538        // consist, and add it to the consist if it is
539        if (!consistManager.getConsist(address).isAddressAllowed(locoaddress)) {
540            JmriJOptionPane.showMessageDialog(this,
541                    Bundle.getMessage("AddressNotAllowedError"));
542            return;
543        }
544        if (consistManager.getConsist(address).contains(locoaddress)) {
545            JmriJOptionPane.showMessageDialog(this,
546                    Bundle.getMessage("AddressAlreadyInConsistError"));
547            return;
548        } 
549            
550        Consist tempConsist = consistManager.getConsist(address);
551        tempConsist.add(locoaddress, locoDirectionNormal.isSelected());
552        
553        // Try to get a roster entry
554        RosterEntry re = null;
555        if (locoRosterBox.getSelectedRosterEntries().length == 1) {
556            re = locoRosterBox.getSelectedRosterEntries()[0];
557        } else {
558            List<RosterEntry> res = Roster.getDefault().matchingList(null, null, "" + locoaddress.getNumber(), null, null, null, null);
559            if (!res.isEmpty()) {
560                re = res.get(0);
561            }
562        }
563                        
564        if (re != null) {    
565            tempConsist.setRosterId(locoaddress, re.titleString());
566        }        
567            
568        if (consistComboBox.getSelectedItem() != adrSelector.getAddress()) {
569            initializeConsistBox();
570            consistComboBox.setSelectedItem(adrSelector.getAddress());
571        }
572        consistManager.notifyConsistListChanged();
573        consistModel.fireTableDataChanged();
574        resetLocoButtonActionPerformed(e);        
575    }
576
577    public void locoSelected() {
578        if (locoRosterBox.getSelectedRosterEntries().length == 1) {
579            locoSelector.setAddress(locoRosterBox.getSelectedRosterEntries()[0].getDccLocoAddress());
580        }
581    }
582
583    /**
584     * we're registering as a listener for Consist events, so we need to
585     * implement the interface.
586     * {@inheritDoc}
587     */
588    @Override
589    public void consistReply(LocoAddress locoaddress, int status) {
590        log.debug("Consist Reply received for Locomotive {} with status {}", locoaddress, status);
591        _status.setText(consistManager.decodeErrorCode(status));
592        // For some status codes, we want to trigger specific actions
593        //if((status & jmri.ConsistListener.CONSIST_FULL)!=0) {
594        // canAdd();
595        //} else {
596        canAdd();
597        //}
598        consistModel.fireTableDataChanged();
599        try {
600            consistFile.writeFile(consistManager.getConsistList());
601        } catch (IOException e) {
602            log.warn("error writing consist file: {}", e.getMessage());
603        }
604    }
605
606    @Override
607    public void dispose() {
608        super.dispose();
609        // de-register to be notified if the consist list changes.
610        consistManager.removeConsistListListener(this);
611    }
612
613    // ConsistListListener interface
614    /**
615     * {@inheritDoc}
616     */
617    @Override
618    public void notifyConsistListChanged() {
619        // Save consist file
620        try {
621            consistFile.writeFile(consistManager.getConsistList());
622        } catch (IOException e) {
623            log.warn("error writing consist file: {}", e.getMessage());
624        }  
625        // update the consist list.
626        initializeConsistBox();
627    }
628
629    /**
630     * private method to scan the roster for consists
631     */
632    private void scanRoster(){
633       List<RosterEntry> roster = Roster.getDefault().getAllEntries();
634       for(RosterEntry entry:roster){
635            DccLocoAddress address = entry.getDccLocoAddress();
636            CvTableModel  cvTable = new CvTableModel(_status, null);  // will hold CV objects
637            entry.readFile();  // read, but don't yet process
638
639            entry.loadCvModel(null, cvTable);
640            CvValue cv19Value = cvTable.getCvByNumber("19");
641            if(cv19Value!=null && (cv19Value.getValue() & 0x7F)!=0){
642                boolean direction = ((cv19Value.getValue()&0x80)==0);
643                DccLocoAddress consistAddress = new DccLocoAddress((cv19Value.getValue()&0x7f),false);
644                /*
645                 * Make sure the marked consist type is an advanced consist.
646                 * this consist
647                  */
648                Consist consist = consistManager.getConsist(consistAddress);
649                if (Consist.ADVANCED_CONSIST != consist.getConsistType()) {
650                    consist.setConsistType(Consist.ADVANCED_CONSIST);
651                }
652
653                if (!consist.contains(address)) {
654                   consist.add(address, direction );
655                   consist.setRosterId(address, entry.titleString());
656                }
657            }
658       }
659    }
660
661    private void reportNoConsistSeletected(){
662        JmriJOptionPane.showMessageDialog(this,
663                Bundle.getMessage("NoConsistSelectedError"));
664
665    }
666
667    public void setDefaultStatus() {
668        _status.setText(Bundle.getMessage("DefaultStatusText"));
669    }
670
671    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConsistToolFrame.class);
672
673}