001package jmri.jmrit.operations.rollingstock.engines.gui; 002 003import java.awt.Font; 004import java.beans.PropertyChangeEvent; 005import java.beans.PropertyChangeListener; 006import java.util.List; 007 008import javax.swing.*; 009import javax.swing.table.TableCellEditor; 010 011import jmri.InstanceManager; 012import jmri.jmrit.operations.OperationsTableModel; 013import jmri.jmrit.operations.rollingstock.RollingStock; 014import jmri.jmrit.operations.rollingstock.engines.*; 015import jmri.jmrit.operations.setup.Control; 016import jmri.jmrit.operations.setup.Setup; 017import jmri.util.swing.XTableColumnModel; 018import jmri.util.table.ButtonEditor; 019import jmri.util.table.ButtonRenderer; 020 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024/** 025 * Table Model for edit of engines used by operations 026 * 027 * @author Daniel Boudreau Copyright (C) 2008, 2012, 2025, 2026 028 */ 029public class EnginesTableModel extends OperationsTableModel implements PropertyChangeListener { 030 031 EngineManager engineManager = InstanceManager.getDefault(EngineManager.class); // There is only one manager 032 033 // Defines the columns 034 private static final int SELECT_COLUMN = 0; 035 private static final int NUM_COLUMN = 1; 036 private static final int ROAD_COLUMN = 2; 037 private static final int MODEL_COLUMN = 3; 038 private static final int HP_COLUMN = 4; 039 private static final int WEIGHT_COLUMN = 5; 040 private static final int TYPE_COLUMN = 6; 041 private static final int LENGTH_COLUMN = 7; 042 private static final int COLOR_COLUMN = 8; 043 private static final int CONSIST_COLUMN = 9; 044 private static final int LOCATION_COLUMN = 10; 045 private static final int RFID_WHERE_LAST_SEEN_COLUMN = 11; 046 private static final int RFID_WHEN_LAST_SEEN_COLUMN = 12; 047 private static final int DESTINATION_COLUMN = 13; 048 private static final int PREVIOUS_LOCATION_COLUMN = 14; 049 private static final int TRAIN_COLUMN = 15; 050 private static final int LAST_TRAIN_COLUMN = 16; 051 private static final int MOVES_COLUMN = 17; 052 private static final int BUILT_COLUMN = 18; 053 private static final int OWNER_COLUMN = 19; 054 private static final int VALUE_COLUMN = 20; 055 private static final int RFID_COLUMN = 21; 056 private static final int LAST_COLUMN = 22; 057 private static final int DCC_ADDRESS_COLUMN = 23; 058 private static final int PICKUP_COLUMN = 24; 059 private static final int SETOUT_COLUMN = 25; 060 private static final int COMMENT_COLUMN = 26; 061 private static final int SET_COLUMN = 27; 062 private static final int EDIT_COLUMN = 28; 063 064 private static final int HIGHEST_COLUMN = EDIT_COLUMN + 1; 065 066 public EnginesTableModel(boolean showAllLocos, String locationName, String trackName) { 067 super(); 068 showAll = showAllLocos; 069 this.locationName = locationName; 070 this.trackName = trackName; 071 engineManager.addPropertyChangeListener(this); 072 updateList(); 073 } 074 075 public final int SORTBY_NUMBER = 0; 076 public final int SORTBY_ROAD = 1; 077 public final int SORTBY_MODEL = 2; 078 public final int SORTBY_LOCATION = 3; 079 public final int SORTBY_DESTINATION = 4; 080 public final int SORTBY_TRAIN = 5; 081 public final int SORTBY_MOVES = 6; 082 public final int SORTBY_CONSIST = 7; 083 public final int SORTBY_BUILT = 8; 084 public final int SORTBY_OWNER = 9; 085 public final int SORTBY_VALUE = 10; 086 public final int SORTBY_RFID = 11; 087 public final int SORTBY_LAST = 12; 088 public final int SORTBY_HP = 13; 089 public final int SORTBY_DCC_ADDRESS = 14; 090 public final int SORTBY_PICKUP = 15; 091 public final int SORTBY_COMMENT = 16; 092 093 private int _sort = SORTBY_NUMBER; 094 095 /** 096 * Not all columns are visible at the same time. 097 * 098 * @param sort which sort is active 099 */ 100 public void setSort(int sort) { 101 _sort = sort; 102 updateList(); 103 if (sort == SORTBY_MOVES || 104 sort == SORTBY_BUILT || 105 sort == SORTBY_OWNER || 106 sort == SORTBY_VALUE || 107 sort == SORTBY_RFID || 108 sort == SORTBY_LAST || 109 sort == SORTBY_DCC_ADDRESS || 110 sort == SORTBY_PICKUP || 111 sort == SORTBY_COMMENT) { 112 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 113 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), sort == SORTBY_MOVES); 114 tcm.setColumnVisible(tcm.getColumnByModelIndex(BUILT_COLUMN), sort == SORTBY_BUILT); 115 tcm.setColumnVisible(tcm.getColumnByModelIndex(OWNER_COLUMN), sort == SORTBY_OWNER); 116 tcm.setColumnVisible(tcm.getColumnByModelIndex(VALUE_COLUMN), sort == SORTBY_VALUE); 117 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_COLUMN), sort == SORTBY_RFID); 118 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHEN_LAST_SEEN_COLUMN), sort == SORTBY_RFID); 119 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHERE_LAST_SEEN_COLUMN), sort == SORTBY_RFID); 120 tcm.setColumnVisible(tcm.getColumnByModelIndex(PREVIOUS_LOCATION_COLUMN), sort == SORTBY_LAST); 121 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_COLUMN), sort == SORTBY_LAST); 122 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), sort == SORTBY_LAST); 123 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_COLUMN), true); 124 tcm.setColumnVisible(tcm.getColumnByModelIndex(PICKUP_COLUMN), sort == SORTBY_PICKUP); 125 tcm.setColumnVisible(tcm.getColumnByModelIndex(SETOUT_COLUMN), sort == SORTBY_PICKUP); 126 tcm.setColumnVisible(tcm.getColumnByModelIndex(DCC_ADDRESS_COLUMN), sort == SORTBY_DCC_ADDRESS); 127 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), sort == SORTBY_COMMENT); 128 } 129 fireTableDataChanged(); 130 } 131 132 public void toggleSelectVisible() { 133 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 134 tcm.setColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN), 135 !tcm.isColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN))); 136 } 137 138 public void resetCheckboxes() { 139 for (Engine engine : engineList) { 140 engine.setSelected(false); 141 } 142 } 143 144 public String getSortByName() { 145 return getSortByName(_sort); 146 } 147 148 public String getSortByName(int sort) { 149 switch (sort) { 150 case SORTBY_NUMBER: 151 return Bundle.getMessage("Number"); 152 case SORTBY_ROAD: 153 return Bundle.getMessage("Road"); 154 case SORTBY_MODEL: 155 return Bundle.getMessage("Model"); 156 case SORTBY_LOCATION: 157 return Bundle.getMessage("Location"); 158 case SORTBY_DESTINATION: 159 return Bundle.getMessage("Destination"); 160 case SORTBY_TRAIN: 161 return Bundle.getMessage("Train"); 162 case SORTBY_MOVES: 163 return Bundle.getMessage("Moves"); 164 case SORTBY_CONSIST: 165 return Bundle.getMessage("Consist"); 166 case SORTBY_BUILT: 167 return Bundle.getMessage("Built"); 168 case SORTBY_OWNER: 169 return Bundle.getMessage("Owner"); 170 case SORTBY_DCC_ADDRESS: 171 return Bundle.getMessage("DccAddress"); 172 case SORTBY_HP: 173 return Bundle.getMessage("HP"); 174 case SORTBY_VALUE: 175 return Setup.getValueLabel(); 176 case SORTBY_RFID: 177 return Setup.getRfidLabel(); 178 case SORTBY_LAST: 179 return Bundle.getMessage("Last"); 180 case SORTBY_COMMENT: 181 return Bundle.getMessage("Comment"); 182 default: 183 return Bundle.getMessage("ErrorTitle"); // NOI18N 184 } 185 } 186 187 /** 188 * Search for engine by road number 189 * 190 * @param roadNumber The string road number to search for. 191 * @return -1 if not found, table row number if found 192 */ 193 public int findEngineByRoadNumber(String roadNumber) { 194 return findRollingStockByRoadNumber(roadNumber, engineList); 195 } 196 197 public Engine getEngineAtIndex(int index) { 198 return engineList.get(index); 199 } 200 201 private void updateList() { 202 // first, remove listeners from the individual objects 203 removePropertyChangeEngines(); 204 engineList = getSelectedEngineList(); 205 // and add listeners back in 206 addPropertyChangeEngines(); 207 } 208 209 public List<Engine> getSelectedEngineList() { 210 return getEngineList(_sort); 211 } 212 213 public List<Engine> getEngineList(int sort) { 214 List<Engine> list; 215 switch (sort) { 216 case SORTBY_ROAD: 217 list = engineManager.getByRoadNameList(); 218 break; 219 case SORTBY_MODEL: 220 list = engineManager.getByModelList(); 221 break; 222 case SORTBY_LOCATION: 223 list = engineManager.getByLocationList(); 224 break; 225 case SORTBY_DESTINATION: 226 list = engineManager.getByDestinationList(); 227 break; 228 case SORTBY_TRAIN: 229 list = engineManager.getByTrainList(); 230 break; 231 case SORTBY_MOVES: 232 list = engineManager.getByMovesList(); 233 break; 234 case SORTBY_CONSIST: 235 list = engineManager.getByConsistList(); 236 break; 237 case SORTBY_OWNER: 238 list = engineManager.getByOwnerList(); 239 break; 240 case SORTBY_BUILT: 241 list = engineManager.getByBuiltList(); 242 break; 243 case SORTBY_VALUE: 244 list = engineManager.getByValueList(); 245 break; 246 case SORTBY_RFID: 247 list = engineManager.getByRfidList(); 248 break; 249 case SORTBY_LAST: 250 list = engineManager.getByLastDateList(); 251 break; 252 case SORTBY_PICKUP: 253 list = engineManager.getByPickupList(); 254 break; 255 case SORTBY_COMMENT: 256 list = engineManager.getByCommentList(); 257 break; 258 case SORTBY_NUMBER: 259 default: 260 list = engineManager.getByNumberList(); 261 } 262 filterList(list); 263 return list; 264 } 265 266 List<Engine> engineList = null; 267 268 EnginesTableFrame _frame; 269 270 void initTable(JTable table, EnginesTableFrame frame) { 271 super.initTable(table); 272 _frame = frame; 273 initTable(); 274 } 275 276 // Default engines frame table column widths, starts with Number column and ends with Edit 277 private final int[] _enginesTableColumnWidths = 278 {60, 60, 60, 65, 50, 65, 65, 65, 35, 75, 190, 190, 190, 140, 190, 65, 90, 50, 50, 50, 50, 100, 130, 50, 50, 279 50, 100, 65, 70}; 280 281 void initTable() { 282 // Use XTableColumnModel so we can control which columns are visible 283 XTableColumnModel tcm = new XTableColumnModel(); 284 _table.setColumnModel(tcm); 285 _table.createDefaultColumnsFromModel(); 286 287 // Install the button handlers 288 ButtonRenderer buttonRenderer = new ButtonRenderer(); 289 tcm.getColumn(SET_COLUMN).setCellRenderer(buttonRenderer); 290 TableCellEditor buttonEditor = new ButtonEditor(new javax.swing.JButton()); 291 tcm.getColumn(SET_COLUMN).setCellEditor(buttonEditor); 292 tcm.getColumn(EDIT_COLUMN).setCellRenderer(buttonRenderer); 293 tcm.getColumn(EDIT_COLUMN).setCellEditor(buttonEditor); 294 295 // set column preferred widths 296 // load defaults, xml file data not found 297 for (int i = 0; i < tcm.getColumnCount(); i++) { 298 tcm.getColumn(i).setPreferredWidth(_enginesTableColumnWidths[i]); 299 } 300 _frame.loadTableDetails(_table); 301 302 // turn off columns 303 tcm.setColumnVisible(tcm.getColumnByModelIndex(BUILT_COLUMN), false); 304 tcm.setColumnVisible(tcm.getColumnByModelIndex(OWNER_COLUMN), false); 305 tcm.setColumnVisible(tcm.getColumnByModelIndex(VALUE_COLUMN), false); 306 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_COLUMN), false); 307 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHEN_LAST_SEEN_COLUMN), false); 308 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHERE_LAST_SEEN_COLUMN), false); 309 tcm.setColumnVisible(tcm.getColumnByModelIndex(PREVIOUS_LOCATION_COLUMN), false); 310 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_COLUMN), false); 311 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), false); 312 tcm.setColumnVisible(tcm.getColumnByModelIndex(DCC_ADDRESS_COLUMN), false); 313 tcm.setColumnVisible(tcm.getColumnByModelIndex(PICKUP_COLUMN), false); 314 tcm.setColumnVisible(tcm.getColumnByModelIndex(SETOUT_COLUMN), false); 315 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), false); 316 317 // turn on default 318 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), true); 319 } 320 321 @Override 322 public int getRowCount() { 323 return engineList.size(); 324 } 325 326 @Override 327 public int getColumnCount() { 328 return HIGHEST_COLUMN; 329 } 330 331 @Override 332 public String getColumnName(int col) { 333 switch (col) { 334 case SELECT_COLUMN: 335 return Bundle.getMessage("ButtonSelect"); 336 case NUM_COLUMN: 337 return Bundle.getMessage("Number"); 338 case ROAD_COLUMN: 339 return Bundle.getMessage("Road"); 340 case MODEL_COLUMN: 341 return Bundle.getMessage("Model"); 342 case HP_COLUMN: 343 return Bundle.getMessage("HP"); 344 case TYPE_COLUMN: 345 return Bundle.getMessage("Type"); 346 case COLOR_COLUMN: 347 return Bundle.getMessage("Color"); 348 case LENGTH_COLUMN: 349 return Bundle.getMessage("Len"); 350 case WEIGHT_COLUMN: 351 return Bundle.getMessage("Weight"); 352 case CONSIST_COLUMN: 353 return Bundle.getMessage("Consist"); 354 case LOCATION_COLUMN: 355 return Bundle.getMessage("Location"); 356 case RFID_WHERE_LAST_SEEN_COLUMN: 357 return Bundle.getMessage("WhereLastSeen"); 358 case RFID_WHEN_LAST_SEEN_COLUMN: 359 return Bundle.getMessage("WhenLastSeen"); 360 case DESTINATION_COLUMN: 361 return Bundle.getMessage("Destination"); 362 case PREVIOUS_LOCATION_COLUMN: 363 return Bundle.getMessage("LastLocation"); 364 case TRAIN_COLUMN: 365 return Bundle.getMessage("Train"); 366 case LAST_TRAIN_COLUMN: 367 return Bundle.getMessage("LastTrain"); 368 case MOVES_COLUMN: 369 return Bundle.getMessage("Moves"); 370 case BUILT_COLUMN: 371 return Bundle.getMessage("Built"); 372 case OWNER_COLUMN: 373 return Bundle.getMessage("Owner"); 374 case VALUE_COLUMN: 375 return Setup.getValueLabel(); 376 case RFID_COLUMN: 377 return Setup.getRfidLabel(); 378 case LAST_COLUMN: 379 return Bundle.getMessage("LastMoved"); 380 case DCC_ADDRESS_COLUMN: 381 return Bundle.getMessage("DccAddress"); 382 case PICKUP_COLUMN: 383 return Bundle.getMessage("Pickup"); 384 case SETOUT_COLUMN: 385 return Bundle.getMessage("SetOut"); 386 case COMMENT_COLUMN: 387 return Bundle.getMessage("Comment"); 388 case SET_COLUMN: 389 return Bundle.getMessage("Set"); 390 case EDIT_COLUMN: 391 return Bundle.getMessage("ButtonEdit"); // titles above all columns 392 default: 393 return "unknown"; // NOI18N 394 } 395 } 396 397 @Override 398 public Class<?> getColumnClass(int col) { 399 switch (col) { 400 case SELECT_COLUMN: 401 return Boolean.class; 402 case SET_COLUMN: 403 case EDIT_COLUMN: 404 return JButton.class; 405 case LENGTH_COLUMN: 406 case MOVES_COLUMN: 407 return Integer.class; 408 default: 409 return String.class; 410 } 411 } 412 413 @Override 414 public boolean isCellEditable(int row, int col) { 415 Engine engine = engineList.get(row); 416 if (engine.isClone()) { 417 return false; 418 } 419 switch (col) { 420 case SELECT_COLUMN: 421 case SET_COLUMN: 422 case EDIT_COLUMN: 423 case MOVES_COLUMN: 424 case VALUE_COLUMN: 425 case RFID_COLUMN: 426 return true; 427 default: 428 return false; 429 } 430 } 431 432 @Override 433 public Object getValueAt(int row, int col) { 434 if (row >= getRowCount()) { 435 return "ERROR row " + row; // NOI18N 436 } 437 Engine engine = engineList.get(row); 438 if (engine == null) { 439 return "ERROR engine unknown " + row; // NOI18N 440 } 441 if (engine.isClone()) { 442 setToolTip(Bundle.getMessage("DoNotModifyClone", engine.toString()), col); 443 } else { 444 setToolTip(null, col); 445 } 446 switch (col) { 447 case SELECT_COLUMN: 448 return engine.isSelected(); 449 case NUM_COLUMN: 450 return engine.getNumber(); 451 case ROAD_COLUMN: 452 return engine.getRoadName(); 453 case COLOR_COLUMN: 454 return engine.getColorName(); 455 case LENGTH_COLUMN: 456 return engine.getLengthInteger(); 457 case MODEL_COLUMN: 458 return engine.getModel(); 459 case HP_COLUMN: 460 return engine.getHp(); 461 case TYPE_COLUMN: { 462 if (engine.isBunit()) { 463 return engine.getTypeName() + " " + Bundle.getMessage("(B)"); 464 } 465 return engine.getTypeName(); 466 } 467 case WEIGHT_COLUMN: 468 return engine.getWeightTons(); 469 case CONSIST_COLUMN: { 470 if (engine.isLead()) { 471 return engine.getConsistName() + "*"; 472 } 473 return engine.getConsistName(); 474 } 475 case LOCATION_COLUMN: { 476 String s = engine.getStatus(); 477 if (!engine.getLocationName().equals(Engine.NONE)) { 478 s = engine.getStatus() + engine.getLocationName() + " (" + engine.getTrackName() + ")"; 479 } 480 return s; 481 } 482 case RFID_WHERE_LAST_SEEN_COLUMN: { 483 return engine.getWhereLastSeenName() + 484 (engine.getTrackLastSeenName().equals(Engine.NONE) ? "" 485 : " (" + engine.getTrackLastSeenName() + ")"); 486 } 487 case RFID_WHEN_LAST_SEEN_COLUMN: { 488 return engine.getWhenLastSeenDate(); 489 } 490 case DESTINATION_COLUMN: { 491 String s = ""; 492 if (!engine.getDestinationName().equals(Engine.NONE)) { 493 s = engine.getDestinationName() + " (" + engine.getDestinationTrackName() + ")"; 494 } 495 return s; 496 } 497 case PREVIOUS_LOCATION_COLUMN: { 498 String s = ""; 499 if (!engine.getLastLocationName().equals(Engine.NONE)) { 500 s = engine.getLastLocationName() + " (" + engine.getLastTrackName() + ")"; 501 } 502 return s; 503 } 504 case TRAIN_COLUMN: { 505 // if train was manually set by user add an asterisk 506 if (engine.getTrain() != null && engine.getRouteLocation() == null) { 507 return engine.getTrainName() + "*"; 508 } 509 return engine.getTrainName(); 510 } 511 case LAST_TRAIN_COLUMN: 512 return engine.getLastTrainName(); 513 case MOVES_COLUMN: 514 return engine.getMoves(); 515 case BUILT_COLUMN: 516 return engine.getBuilt(); 517 case OWNER_COLUMN: 518 return engine.getOwnerName(); 519 case VALUE_COLUMN: 520 return engine.getValue(); 521 case RFID_COLUMN: 522 return engine.getRfid(); 523 case LAST_COLUMN: 524 return engine.getSortDate(); 525 case DCC_ADDRESS_COLUMN: 526 return engine.getDccAddress(); 527 case PICKUP_COLUMN: 528 return engine.getPickupTime(); 529 case SETOUT_COLUMN: 530 return engine.getSetoutTime(); 531 case COMMENT_COLUMN: 532 return engine.getComment(); 533 case SET_COLUMN: 534 return Bundle.getMessage("Set"); 535 case EDIT_COLUMN: 536 return Bundle.getMessage("ButtonEdit"); 537 default: 538 return "unknown " + col; // NOI18N 539 } 540 } 541 542 EngineEditFrame engineEditFrame = null; 543 EngineSetFrame engineSetFrame = null; 544 545 @Override 546 public void setValueAt(Object value, int row, int col) { 547 Engine engine = engineList.get(row); 548 switch (col) { 549 case SELECT_COLUMN: 550 engine.setSelected(((Boolean) value).booleanValue()); 551 break; 552 case MOVES_COLUMN: 553 try { 554 engine.setMoves(Integer.parseInt(value.toString())); 555 } catch (NumberFormatException e) { 556 log.error("move count must be a number"); 557 } 558 break; 559 case BUILT_COLUMN: 560 engine.setBuilt(value.toString()); 561 break; 562 case OWNER_COLUMN: 563 engine.setOwnerName(value.toString()); 564 break; 565 case VALUE_COLUMN: 566 engine.setValue(value.toString()); 567 break; 568 case RFID_COLUMN: 569 engine.setRfid(value.toString()); 570 break; 571 case SET_COLUMN: 572 log.debug("Set engine location"); 573 if (engineSetFrame != null) { 574 engineSetFrame.dispose(); 575 } 576 // use invokeLater so new window appears on top 577 SwingUtilities.invokeLater(() -> { 578 engineSetFrame = new EngineSetFrame(); 579 engineSetFrame.initComponents(); 580 engineSetFrame.load(engine); 581 }); 582 break; 583 case EDIT_COLUMN: 584 log.debug("Edit engine"); 585 if (engineEditFrame != null) { 586 engineEditFrame.dispose(); 587 } 588 // use invokeLater so new window appears on top 589 SwingUtilities.invokeLater(() -> { 590 engineEditFrame = new EngineEditFrame(); 591 engineEditFrame.initComponents(); 592 engineEditFrame.load(engine); 593 }); 594 break; 595 default: 596 break; 597 } 598 } 599 600 @Override 601 protected Font getFont(int row) { 602 Engine eng = engineList.get(row); 603 if (eng.isClone() || engineManager.getClone(eng) != null) { 604 Font font = super.getFont(row); 605 font = new Font(font.getFontName(), Font.ITALIC, font.getSize()); 606 return font; 607 } 608 return super.getFont(row); 609 } 610 611 public void dispose() { 612 log.debug("dispose EngineTableModel"); 613 engineManager.removePropertyChangeListener(this); 614 removePropertyChangeEngines(); 615 if (engineSetFrame != null) { 616 engineSetFrame.dispose(); 617 } 618 if (engineEditFrame != null) { 619 engineEditFrame.dispose(); 620 } 621 } 622 623 private void addPropertyChangeEngines() { 624 for (RollingStock rs : engineManager.getList()) { 625 rs.addPropertyChangeListener(this); 626 } 627 } 628 629 private void removePropertyChangeEngines() { 630 for (RollingStock rs : engineManager.getList()) { 631 rs.removePropertyChangeListener(this); 632 } 633 } 634 635 @Override 636 public void propertyChange(PropertyChangeEvent e) { 637 if (Control.SHOW_PROPERTY) { 638 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 639 .getNewValue()); 640 } 641 if (e.getPropertyName().equals(EngineManager.LISTLENGTH_CHANGED_PROPERTY) || 642 e.getPropertyName().equals(ConsistManager.LISTLENGTH_CHANGED_PROPERTY)) { 643 updateList(); 644 fireTableDataChanged(); 645 } 646 // Engine length, type, and HP are based on model, so multiple changes 647 else if (e.getPropertyName().equals(Engine.LENGTH_CHANGED_PROPERTY) || 648 e.getPropertyName().equals(Engine.TYPE_CHANGED_PROPERTY) || 649 e.getPropertyName().equals(Engine.HP_CHANGED_PROPERTY)) { 650 fireTableDataChanged(); 651 } 652 // must be a engine change 653 else if (e.getSource().getClass().equals(Engine.class)) { 654 Engine engine = (Engine) e.getSource(); 655 int row = engineList.indexOf(engine); 656 if (Control.SHOW_PROPERTY) { 657 log.debug("Update engine table row: {}", row); 658 } 659 if (row >= 0) { 660 fireTableRowsUpdated(row, row); 661 // next is needed when only showing engines at a location or track 662 } else if (e.getPropertyName().equals(Engine.TRACK_CHANGED_PROPERTY)) { 663 updateList(); 664 fireTableDataChanged(); 665 } 666 } 667 } 668 669 private static final Logger log = LoggerFactory.getLogger(EnginesTableModel.class); 670}