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