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