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