001package jmri.jmrit.operations.rollingstock.cars.gui; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004 005import java.awt.Color; 006import java.awt.Font; 007import java.beans.PropertyChangeEvent; 008import java.beans.PropertyChangeListener; 009import java.util.List; 010 011import javax.swing.*; 012import javax.swing.table.TableCellEditor; 013 014import jmri.InstanceManager; 015import jmri.jmrit.operations.OperationsTableModel; 016import jmri.jmrit.operations.rollingstock.cars.*; 017import jmri.jmrit.operations.setup.Control; 018import jmri.jmrit.operations.setup.Setup; 019import jmri.util.swing.XTableColumnModel; 020import jmri.util.table.ButtonEditor; 021import jmri.util.table.ButtonRenderer; 022 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026/** 027 * Table Model for edit of cars used by operations 028 * 029 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012, 2016, 2025, 2026 030 */ 031public class CarsTableModel extends OperationsTableModel implements PropertyChangeListener { 032 033 CarManager carManager = InstanceManager.getDefault(CarManager.class); // There is only one manager 034 035 // Defines the columns 036 private static final int SELECT_COLUMN = 0; 037 private static final int NUMBER_COLUMN = 1; 038 private static final int ROAD_COLUMN = 2; 039 private static final int TYPE_COLUMN = 3; 040 private static final int LENGTH_COLUMN = 4; 041 private static final int LOAD_COLUMN = 5; 042 private static final int RWE_LOAD_COLUMN = 6; 043 private static final int RWL_LOAD_COLUMN = 7; 044 private static final int COLOR_COLUMN = 8; 045 private static final int KERNEL_COLUMN = 9; 046 private static final int LOCATION_COLUMN = 10; 047 private static final int RFID_WHERE_LAST_SEEN_COLUMN = 11; 048 private static final int RFID_WHEN_LAST_SEEN_COLUMN = 12; 049 private static final int DESTINATION_COLUMN = 13; 050 private static final int FINAL_DESTINATION_COLUMN = 14; 051 private static final int RWE_DESTINATION_COLUMN = 15; 052 private static final int RWL_DESTINATION_COLUMN = 16; 053 private static final int ROUTE_COLUMN = 17; 054 private static final int LAST_LOCATION_COLUMN = 18; 055 private static final int DIVISION_COLUMN = 19; 056 private static final int TRAIN_COLUMN = 20; 057 private static final int LAST_TRAIN_COLUMN = 21; 058 private static final int MOVES_COLUMN = 22; 059 private static final int BUILT_COLUMN = 23; 060 private static final int OWNER_COLUMN = 24; 061 private static final int VALUE_COLUMN = 25; 062 private static final int RFID_COLUMN = 26; 063 private static final int WAIT_COLUMN = 27; 064 private static final int PICKUP_COLUMN = 28; 065 private static final int SETOUT_COLUMN = 29; 066 private static final int LAST_COLUMN = 30; 067 private static final int COMMENT_COLUMN = 31; 068 private static final int SET_COLUMN = 32; 069 private static final int EDIT_COLUMN = 33; 070 071 private static final int HIGHESTCOLUMN = EDIT_COLUMN + 1; 072 073 public final int SORTBY_NUMBER = 0; 074 public final int SORTBY_ROAD = 1; 075 public final int SORTBY_TYPE = 2; 076 public final int SORTBY_LOCATION = 3; 077 public final int SORTBY_DESTINATION = 4; 078 public final int SORTBY_TRAIN = 5; 079 public final int SORTBY_MOVES = 6; 080 public final int SORTBY_KERNEL = 7; 081 public final int SORTBY_LOAD = 8; 082 public final int SORTBY_COLOR = 9; 083 public final int SORTBY_BUILT = 10; 084 public final int SORTBY_OWNER = 11; 085 public final int SORTBY_RFID = 12; 086 public final int SORTBY_RWE = 13; // return when empty 087 public final int SORTBY_RWL = 14; // return when loaded 088 public final int SORTBY_ROUTE = 15; 089 public final int SORTBY_DIVISION = 16; 090 public final int SORTBY_FINALDESTINATION = 17; 091 public final int SORTBY_VALUE = 18; 092 public final int SORTBY_WAIT = 19; 093 public final int SORTBY_PICKUP = 20; 094 public final int SORTBY_LAST = 21; 095 public final int SORTBY_COMMENT = 22; // also used by PrintCarRosterAction 096 097 private int _sort = SORTBY_NUMBER; 098 099 List<Car> carList = null; // list of cars 100 // JTable _table; 101 CarsTableFrame _frame; 102 103 public CarsTableModel(boolean showAllCars, String locationName, String trackName) { 104 super(); 105 showAll = showAllCars; 106 this.locationName = locationName; 107 this.trackName = trackName; 108 carManager.addPropertyChangeListener(this); 109 updateList(); 110 } 111 112 /** 113 * Not all columns in the Cars table are shown. This was done to limit the 114 * width of the table. Only one column from the following groups is shown at 115 * any one time. 116 * <p> 117 * Load, Color, and RWE Load are grouped together. 118 * <p> 119 * Destination, Final Destination, and RWE Destination are grouped together. 120 * <p> 121 * Moves, Built, Owner, Value, RFID, Wait, Pickup, and Last are grouped 122 * together. 123 * 124 * @param sort The integer sort to use. 125 */ 126 public void setSort(int sort) { 127 _sort = sort; 128 updateList(); 129 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 130 if (sort == SORTBY_COLOR || sort == SORTBY_LOAD || sort == SORTBY_RWE || sort == SORTBY_RWL) { 131 tcm.setColumnVisible(tcm.getColumnByModelIndex(LOAD_COLUMN), sort == SORTBY_LOAD); 132 tcm.setColumnVisible(tcm.getColumnByModelIndex(COLOR_COLUMN), sort == SORTBY_COLOR); 133 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_LOAD_COLUMN), sort == SORTBY_RWE); 134 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_LOAD_COLUMN), sort == SORTBY_RWL); 135 } 136 if (sort == SORTBY_DIVISION) { 137 tcm.setColumnVisible(tcm.getColumnByModelIndex(DIVISION_COLUMN), true); 138 } 139 if (sort == SORTBY_TRAIN) { 140 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_COLUMN), true); 141 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), false); 142 } 143 if (sort == SORTBY_DESTINATION || 144 sort == SORTBY_FINALDESTINATION || 145 sort == SORTBY_RWE || 146 sort == SORTBY_RWL || 147 sort == SORTBY_ROUTE) { 148 tcm.setColumnVisible(tcm.getColumnByModelIndex(DESTINATION_COLUMN), sort == SORTBY_DESTINATION); 149 tcm.setColumnVisible(tcm.getColumnByModelIndex(FINAL_DESTINATION_COLUMN), sort == SORTBY_FINALDESTINATION); 150 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_DESTINATION_COLUMN), sort == SORTBY_RWE); 151 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_DESTINATION_COLUMN), sort == SORTBY_RWL); 152 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_LOAD_COLUMN), sort == SORTBY_RWE); 153 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_LOAD_COLUMN), sort == SORTBY_RWL); 154 tcm.setColumnVisible(tcm.getColumnByModelIndex(ROUTE_COLUMN), sort == SORTBY_ROUTE); 155 156 // show load column if color column isn't visible. 157 tcm.setColumnVisible(tcm.getColumnByModelIndex(LOAD_COLUMN), 158 sort != SORTBY_RWE && 159 sort != SORTBY_RWL && 160 !tcm.isColumnVisible(tcm.getColumnByModelIndex(COLOR_COLUMN))); 161 } else if (sort == SORTBY_MOVES || 162 sort == SORTBY_BUILT || 163 sort == SORTBY_OWNER || 164 sort == SORTBY_VALUE || 165 sort == SORTBY_RFID || 166 sort == SORTBY_WAIT || 167 sort == SORTBY_PICKUP || 168 sort == SORTBY_LAST || 169 sort == SORTBY_COMMENT) { 170 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), sort == SORTBY_MOVES); 171 tcm.setColumnVisible(tcm.getColumnByModelIndex(BUILT_COLUMN), sort == SORTBY_BUILT); 172 tcm.setColumnVisible(tcm.getColumnByModelIndex(OWNER_COLUMN), sort == SORTBY_OWNER); 173 tcm.setColumnVisible(tcm.getColumnByModelIndex(VALUE_COLUMN), sort == SORTBY_VALUE); 174 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_COLUMN), sort == SORTBY_RFID); 175 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHEN_LAST_SEEN_COLUMN), sort == SORTBY_RFID); 176 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHERE_LAST_SEEN_COLUMN), sort == SORTBY_RFID); 177 tcm.setColumnVisible(tcm.getColumnByModelIndex(WAIT_COLUMN), sort == SORTBY_WAIT); 178 tcm.setColumnVisible(tcm.getColumnByModelIndex(PICKUP_COLUMN), sort == SORTBY_PICKUP); 179 tcm.setColumnVisible(tcm.getColumnByModelIndex(SETOUT_COLUMN), sort == SORTBY_PICKUP); 180 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_LOCATION_COLUMN), sort == SORTBY_LAST); 181 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_COLUMN), sort == SORTBY_LAST); 182 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_COLUMN), sort != SORTBY_LAST); 183 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), sort == SORTBY_LAST); 184 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), sort == SORTBY_COMMENT); 185 } 186 fireTableDataChanged(); 187 } 188 189 public String getSortByName() { 190 return getSortByName(_sort); 191 } 192 193 public String getSortByName(int sort) { 194 switch (sort) { 195 case SORTBY_NUMBER: 196 return Bundle.getMessage("Number"); 197 case SORTBY_ROAD: 198 return Bundle.getMessage("Road"); 199 case SORTBY_TYPE: 200 return Bundle.getMessage("Type"); 201 case SORTBY_COLOR: 202 return Bundle.getMessage("Color"); 203 case SORTBY_LOAD: 204 return Bundle.getMessage("Load"); 205 case SORTBY_KERNEL: 206 return Bundle.getMessage("Kernel"); 207 case SORTBY_LOCATION: 208 return Bundle.getMessage("Location"); 209 case SORTBY_DESTINATION: 210 return Bundle.getMessage("Destination"); 211 case SORTBY_DIVISION: 212 return Bundle.getMessage("HomeDivision"); 213 case SORTBY_TRAIN: 214 return Bundle.getMessage("Train"); 215 case SORTBY_FINALDESTINATION: 216 return Bundle.getMessage("FinalDestination"); 217 case SORTBY_RWE: 218 return Bundle.getMessage("ReturnWhenEmpty"); 219 case SORTBY_RWL: 220 return Bundle.getMessage("ReturnWhenLoaded"); 221 case SORTBY_ROUTE: 222 return Bundle.getMessage("Route"); 223 case SORTBY_MOVES: 224 return Bundle.getMessage("Moves"); 225 case SORTBY_BUILT: 226 return Bundle.getMessage("Built"); 227 case SORTBY_OWNER: 228 return Bundle.getMessage("Owner"); 229 case SORTBY_VALUE: 230 return Setup.getValueLabel(); 231 case SORTBY_RFID: 232 return Setup.getRfidLabel(); 233 case SORTBY_WAIT: 234 return Bundle.getMessage("Wait"); 235 case SORTBY_PICKUP: 236 return Bundle.getMessage("Pickup"); 237 case SORTBY_LAST: 238 return Bundle.getMessage("Last"); 239 case SORTBY_COMMENT: 240 return Bundle.getMessage("Comment"); 241 default: 242 return Bundle.getMessage("ErrorTitle"); // NOI18N 243 } 244 } 245 246 @Override 247 protected Color getForegroundColor(int row) { 248 Car car = carList.get(row); 249 if (car.getLocation() != null && car.getTrack() == null) { 250 return Color.red; 251 } 252 return super.getForegroundColor(row); 253 } 254 255 @Override 256 protected Font getFont(int row) { 257 Car car = carList.get(row); 258 if (car.isClone() || carManager.getClone(car) != null) { 259 Font font = super.getFont(row); 260 font = new Font(font.getFontName(), Font.ITALIC, font.getSize()); 261 return font; 262 } 263 return super.getFont(row); 264 } 265 266 public void toggleSelectVisible() { 267 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 268 tcm.setColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN), 269 !tcm.isColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN))); 270 } 271 272 public void resetCheckboxes() { 273 for (Car car : carList) { 274 car.setSelected(false); 275 } 276 } 277 278 /** 279 * Search for car by road number 280 * 281 * @param roadNumber The string road number to search for. 282 * @return -1 if not found, table row number if found 283 */ 284 public int findCarByRoadNumber(String roadNumber) { 285 return findRollingStockByRoadNumber(roadNumber, carList); 286 } 287 288 public Car getCarAtIndex(int index) { 289 return carList.get(index); 290 } 291 292 private void updateList() { 293 // first, remove listeners from the individual objects 294 removePropertyChangeCars(); 295 carList = getSelectedCarList(); 296 // and add listeners back in 297 addPropertyChangeCars(); 298 } 299 300 public List<Car> getSelectedCarList() { 301 return getCarList(_sort); 302 } 303 304 @SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", justification = "default case is sort by number") // NOI18N 305 public List<Car> getCarList(int sort) { 306 List<Car> list; 307 switch (sort) { 308 case SORTBY_NUMBER: 309 list = carManager.getByNumberList(); 310 break; 311 case SORTBY_ROAD: 312 list = carManager.getByRoadNameList(); 313 break; 314 case SORTBY_TYPE: 315 list = carManager.getByTypeList(); 316 break; 317 case SORTBY_COLOR: 318 list = carManager.getByColorList(); 319 break; 320 case SORTBY_LOAD: 321 list = carManager.getByLoadList(); 322 break; 323 case SORTBY_KERNEL: 324 list = carManager.getByKernelList(); 325 break; 326 case SORTBY_LOCATION: 327 list = carManager.getByLocationList(); 328 break; 329 case SORTBY_DESTINATION: 330 list = carManager.getByDestinationList(); 331 break; 332 case SORTBY_TRAIN: 333 list = carManager.getByTrainList(); 334 break; 335 case SORTBY_FINALDESTINATION: 336 list = carManager.getByFinalDestinationList(); 337 break; 338 case SORTBY_RWE: 339 list = carManager.getByRweList(); 340 break; 341 case SORTBY_RWL: 342 list = carManager.getByRwlList(); 343 break; 344 case SORTBY_ROUTE: 345 list = carManager.getByRouteList(); 346 break; 347 case SORTBY_DIVISION: 348 list = carManager.getByDivisionList(); 349 break; 350 case SORTBY_MOVES: 351 list = carManager.getByMovesList(); 352 break; 353 case SORTBY_BUILT: 354 list = carManager.getByBuiltList(); 355 break; 356 case SORTBY_OWNER: 357 list = carManager.getByOwnerList(); 358 break; 359 case SORTBY_VALUE: 360 list = carManager.getByValueList(); 361 break; 362 case SORTBY_RFID: 363 list = carManager.getByRfidList(); 364 break; 365 case SORTBY_WAIT: 366 list = carManager.getByWaitList(); 367 break; 368 case SORTBY_PICKUP: 369 list = carManager.getByPickupList(); 370 break; 371 case SORTBY_LAST: 372 list = carManager.getByLastDateList(); 373 break; 374 case SORTBY_COMMENT: 375 list = carManager.getByCommentList(); 376 break; 377 default: 378 list = carManager.getByNumberList(); 379 } 380 filterCarList(list); 381 return list; 382 } 383 384 private void filterCarList(List<Car> list) { 385 if (!Control.showCloneCars) { 386 for (int i = 0; i < list.size(); i++) { 387 Car car = list.get(i); 388 if (car.isClone()) { 389 list.remove(i--); 390 continue; 391 } 392 } 393 } 394 filterList(list); 395 } 396 397 void initTable(JTable table, CarsTableFrame frame) { 398 super.initTable(table); 399 _frame = frame; 400 initTable(); 401 } 402 403 // Cars frame table column widths, starts with Select column and ends with Edit 404 private final int[] tableColumnWidths = {60, 60, 60, 65, 35, 75, 75, 75, 75, 65, 190, 190, 140, 190, 190, 190, 190, 405 190, 190, 190, 65, 90, 50, 50, 50, 50, 100, 50, 100, 60, 100, 100, 65, 70}; 406 407 void initTable() { 408 // Use XTableColumnModel so we can control which columns are visible 409 XTableColumnModel tcm = new XTableColumnModel(); 410 _table.setColumnModel(tcm); 411 _table.createDefaultColumnsFromModel(); 412 413 // Install the button handlers 414 ButtonRenderer buttonRenderer = new ButtonRenderer(); 415 tcm.getColumn(SET_COLUMN).setCellRenderer(buttonRenderer); 416 TableCellEditor buttonEditor = new ButtonEditor(new javax.swing.JButton()); 417 tcm.getColumn(SET_COLUMN).setCellEditor(buttonEditor); 418 tcm.getColumn(EDIT_COLUMN).setCellRenderer(buttonRenderer); 419 tcm.getColumn(EDIT_COLUMN).setCellEditor(buttonEditor); 420 421 // set column preferred widths 422 for (int i = 0; i < tcm.getColumnCount(); i++) { 423 tcm.getColumn(i).setPreferredWidth(tableColumnWidths[i]); 424 } 425 _frame.loadTableDetails(_table); 426 427 // turn off columns 428 tcm.setColumnVisible(tcm.getColumnByModelIndex(COLOR_COLUMN), false); 429 tcm.setColumnVisible(tcm.getColumnByModelIndex(FINAL_DESTINATION_COLUMN), false); 430 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_DESTINATION_COLUMN), false); 431 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_LOAD_COLUMN), false); 432 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_DESTINATION_COLUMN), false); 433 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_LOAD_COLUMN), false); 434 tcm.setColumnVisible(tcm.getColumnByModelIndex(ROUTE_COLUMN), false); 435 tcm.setColumnVisible(tcm.getColumnByModelIndex(BUILT_COLUMN), false); 436 tcm.setColumnVisible(tcm.getColumnByModelIndex(OWNER_COLUMN), false); 437 tcm.setColumnVisible(tcm.getColumnByModelIndex(VALUE_COLUMN), false); 438 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_COLUMN), false); 439 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHEN_LAST_SEEN_COLUMN), false); 440 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHERE_LAST_SEEN_COLUMN), false); 441 tcm.setColumnVisible(tcm.getColumnByModelIndex(WAIT_COLUMN), false); 442 tcm.setColumnVisible(tcm.getColumnByModelIndex(PICKUP_COLUMN), false); 443 tcm.setColumnVisible(tcm.getColumnByModelIndex(SETOUT_COLUMN), false); 444 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_LOCATION_COLUMN), false); 445 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_COLUMN), false); 446 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), false); 447 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), false); 448 449 // turn on defaults 450 tcm.setColumnVisible(tcm.getColumnByModelIndex(LOAD_COLUMN), true); 451 tcm.setColumnVisible(tcm.getColumnByModelIndex(DESTINATION_COLUMN), true); 452 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), true); 453 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_COLUMN), true); 454 455 tcm.setColumnVisible(tcm.getColumnByModelIndex(DIVISION_COLUMN), carManager.isThereDivisions()); 456 } 457 458 @Override 459 public int getRowCount() { 460 return carList.size(); 461 } 462 463 @Override 464 public int getColumnCount() { 465 return HIGHESTCOLUMN; 466 } 467 468 @Override 469 public String getColumnName(int col) { 470 switch (col) { 471 case SELECT_COLUMN: 472 return Bundle.getMessage("ButtonSelect"); 473 case NUMBER_COLUMN: 474 return Bundle.getMessage("Number"); 475 case ROAD_COLUMN: 476 return Bundle.getMessage("Road"); 477 case LOAD_COLUMN: 478 return Bundle.getMessage("Load"); 479 case COLOR_COLUMN: 480 return Bundle.getMessage("Color"); 481 case TYPE_COLUMN: 482 return Bundle.getMessage("Type"); 483 case LENGTH_COLUMN: 484 return Bundle.getMessage("Len"); 485 case KERNEL_COLUMN: 486 return Bundle.getMessage("Kernel"); 487 case LOCATION_COLUMN: 488 return Bundle.getMessage("Location"); 489 case RFID_WHERE_LAST_SEEN_COLUMN: 490 return Bundle.getMessage("WhereLastSeen"); 491 case RFID_WHEN_LAST_SEEN_COLUMN: 492 return Bundle.getMessage("WhenLastSeen"); 493 case DESTINATION_COLUMN: 494 return Bundle.getMessage("Destination"); 495 case FINAL_DESTINATION_COLUMN: 496 return Bundle.getMessage("FinalDestination"); 497 case RWE_DESTINATION_COLUMN: 498 return Bundle.getMessage("RWELocation"); 499 case RWE_LOAD_COLUMN: 500 return Bundle.getMessage("RWELoad"); 501 case RWL_DESTINATION_COLUMN: 502 return Bundle.getMessage("RWLLocation"); 503 case RWL_LOAD_COLUMN: 504 return Bundle.getMessage("RWLLoad"); 505 case ROUTE_COLUMN: 506 return Bundle.getMessage("Route"); 507 case LAST_LOCATION_COLUMN: 508 return Bundle.getMessage("LastLocation"); 509 case DIVISION_COLUMN: 510 return Bundle.getMessage("HomeDivision"); 511 case TRAIN_COLUMN: 512 return Bundle.getMessage("Train"); 513 case LAST_TRAIN_COLUMN: 514 return Bundle.getMessage("LastTrain"); 515 case MOVES_COLUMN: 516 return Bundle.getMessage("Moves"); 517 case BUILT_COLUMN: 518 return Bundle.getMessage("Built"); 519 case OWNER_COLUMN: 520 return Bundle.getMessage("Owner"); 521 case VALUE_COLUMN: 522 return Setup.getValueLabel(); 523 case RFID_COLUMN: 524 return Setup.getRfidLabel(); 525 case WAIT_COLUMN: 526 return Bundle.getMessage("Wait"); 527 case PICKUP_COLUMN: 528 return Bundle.getMessage("Pickup"); 529 case SETOUT_COLUMN: 530 return Bundle.getMessage("SetOut"); 531 case LAST_COLUMN: 532 return Bundle.getMessage("LastMoved"); 533 case COMMENT_COLUMN: 534 return Bundle.getMessage("Comment"); 535 case SET_COLUMN: 536 return Bundle.getMessage("Set"); 537 case EDIT_COLUMN: 538 return Bundle.getMessage("ButtonEdit"); // titles above all columns 539 default: 540 return "unknown"; // NOI18N 541 } 542 } 543 544 @Override 545 public Class<?> getColumnClass(int col) { 546 switch (col) { 547 case SELECT_COLUMN: 548 return Boolean.class; 549 case SET_COLUMN: 550 case EDIT_COLUMN: 551 return JButton.class; 552 case LENGTH_COLUMN: 553 case MOVES_COLUMN: 554 case WAIT_COLUMN: 555 return Integer.class; 556 default: 557 return String.class; 558 } 559 } 560 561 @Override 562 public boolean isCellEditable(int row, int col) { 563 Car car = carList.get(row); 564 if (car.isClone()) { 565 return false; 566 } 567 switch (col) { 568 case SELECT_COLUMN: 569 case SET_COLUMN: 570 case EDIT_COLUMN: 571 case MOVES_COLUMN: 572 case WAIT_COLUMN: 573 case VALUE_COLUMN: 574 case RFID_COLUMN: 575 return true; 576 default: 577 return false; 578 } 579 } 580 581 @Override 582 public Object getValueAt(int row, int col) { 583 if (row >= getRowCount()) { 584 return "ERROR row " + row; // NOI18N 585 } 586 Car car = carList.get(row); 587 if (car == null) { 588 return "ERROR car unknown " + row; // NOI18N 589 } 590 if (car.isClone()) { 591 setToolTip(Bundle.getMessage("DoNotModifyClone", car.toString()), col); 592 } else { 593 setToolTip(null, col); 594 } 595 switch (col) { 596 case SELECT_COLUMN: 597 return car.isSelected(); 598 case NUMBER_COLUMN: 599 return car.getNumber(); 600 case ROAD_COLUMN: 601 return car.getRoadName(); 602 case LOAD_COLUMN: 603 return getLoadNameString(car); 604 case COLOR_COLUMN: 605 return car.getColor(); 606 case LENGTH_COLUMN: 607 return car.getLengthInteger(); 608 case TYPE_COLUMN: 609 return car.getTypeName() + car.getTypeExtensions(); 610 case KERNEL_COLUMN: 611 if (car.isLead()) { 612 return car.getKernelName() + "*"; 613 } 614 return car.getKernelName(); 615 case LOCATION_COLUMN: 616 if (car.getLocation() != null) { 617 return car.getStatus() + car.getLocationName() + " (" + car.getTrackName() + ")"; 618 } 619 return car.getStatus(); 620 case RFID_WHERE_LAST_SEEN_COLUMN: 621 return car.getWhereLastSeenName() + 622 (car.getTrackLastSeenName().equals(Car.NONE) ? "" : " (" + car.getTrackLastSeenName() + ")"); 623 case RFID_WHEN_LAST_SEEN_COLUMN: { 624 return car.getWhenLastSeenDate(); 625 } 626 case DESTINATION_COLUMN: 627 case FINAL_DESTINATION_COLUMN: { 628 String s = ""; 629 if (car.getDestination() != null) { 630 s = car.getDestinationName() + " (" + car.getDestinationTrackName() + ")"; 631 } 632 if (log.isDebugEnabled() && 633 car.getDestinationTrack() != null && 634 car.getDestinationTrack().getSchedule() != null) { 635 s = s + " " + car.getScheduleItemId() + " "; 636 } 637 if (car.getFinalDestination() != null) { 638 s = s + "->" + car.getFinalDestinationName(); // NOI18N 639 } 640 if (car.getFinalDestinationTrack() != null) { 641 s = s + " (" + car.getFinalDestinationTrackName() + ")"; 642 } 643 if (log.isDebugEnabled() && 644 !s.contains(car.getScheduleItemId()) && 645 car.getFinalDestinationTrack() != null && 646 car.getFinalDestinationTrack().getSchedule() != null) { 647 s = s + " " + car.getScheduleItemId(); 648 } 649 return s; 650 } 651 case RWE_DESTINATION_COLUMN: { 652 String s = car.getReturnWhenEmptyDestinationName(); 653 if (car.getReturnWhenEmptyDestTrack() != null) { 654 s = s + " (" + car.getReturnWhenEmptyDestTrackName() + ")"; 655 } 656 return s; 657 } 658 case RWE_LOAD_COLUMN: 659 return car.getReturnWhenEmptyLoadName(); 660 case RWL_DESTINATION_COLUMN: { 661 String s = car.getReturnWhenLoadedDestinationName(); 662 if (car.getReturnWhenLoadedDestTrack() != null) { 663 s = s + " (" + car.getReturnWhenLoadedDestTrackName() + ")"; 664 } 665 return s; 666 } 667 case RWL_LOAD_COLUMN: 668 return car.getReturnWhenLoadedLoadName(); 669 case ROUTE_COLUMN: 670 return car.getRoutePath(); 671 case DIVISION_COLUMN: 672 return car.getDivisionName(); 673 case LAST_LOCATION_COLUMN: { 674 String s = ""; 675 if (!car.getLastLocationName().equals(Car.NONE)) { 676 s = car.getLastLocationName() + " (" + car.getLastTrackName() + ")"; 677 } 678 return s; 679 } 680 case TRAIN_COLUMN: { 681 // if train was manually set by user add an asterisk 682 if (car.getTrain() != null && car.getRouteLocation() == null) { 683 return car.getTrainName() + "*"; 684 } 685 return car.getTrainName(); 686 } 687 case LAST_TRAIN_COLUMN: 688 return car.getLastTrainName(); 689 case MOVES_COLUMN: 690 return car.getMoves(); 691 case BUILT_COLUMN: 692 return car.getBuilt(); 693 case OWNER_COLUMN: 694 return car.getOwnerName(); 695 case VALUE_COLUMN: 696 return car.getValue(); 697 case RFID_COLUMN: 698 return car.getRfid(); 699 case WAIT_COLUMN: 700 return car.getWait(); 701 case PICKUP_COLUMN: 702 return car.getPickupScheduleName(); 703 case SETOUT_COLUMN: 704 return car.getSetoutTime(); 705 case LAST_COLUMN: 706 return car.getSortDate(); 707 case COMMENT_COLUMN: 708 return car.getComment(); 709 case SET_COLUMN: 710 return Bundle.getMessage("Set"); 711 case EDIT_COLUMN: 712 return Bundle.getMessage("ButtonEdit"); 713 default: 714 return "unknown " + col; // NOI18N 715 } 716 } 717 718 private String getLoadNameString(Car car) { 719 StringBuffer sb = new StringBuffer(car.getLoadName()); 720 if (car.getLoadPriority().equals(CarLoad.PRIORITY_HIGH)) { 721 sb.append(" " + Bundle.getMessage("(P)")); 722 } else if (car.getLoadPriority().equals(CarLoad.PRIORITY_MEDIUM)) { 723 sb.append(" " + Bundle.getMessage("(M)")); 724 } 725 if (car.isCarLoadHazardous()) { 726 sb.append(" " + Bundle.getMessage("(H)")); 727 } 728 return sb.toString(); 729 } 730 731 CarEditFrame cef = null; 732 CarSetFrame csf = null; 733 734 @Override 735 public void setValueAt(Object value, int row, int col) { 736 Car car = carList.get(row); 737 switch (col) { 738 case SELECT_COLUMN: 739 car.setSelected(((Boolean) value).booleanValue()); 740 break; 741 case SET_COLUMN: 742 if (csf != null) { 743 csf.dispose(); 744 } 745 // use invokeLater so new window appears on top 746 SwingUtilities.invokeLater(() -> { 747 csf = new CarSetFrame(); 748 csf.initComponents(); 749 csf.load(car); 750 }); 751 break; 752 case EDIT_COLUMN: 753 if (cef != null) { 754 cef.dispose(); 755 } 756 // use invokeLater so new window appears on top 757 SwingUtilities.invokeLater(() -> { 758 cef = new CarEditFrame(); 759 cef.initComponents(); 760 cef.load(car); 761 }); 762 break; 763 case MOVES_COLUMN: 764 try { 765 car.setMoves(Integer.parseInt(value.toString())); 766 } catch (NumberFormatException e) { 767 log.error("move count must be a number"); 768 } 769 break; 770 case VALUE_COLUMN: 771 car.setValue(value.toString()); 772 break; 773 case RFID_COLUMN: 774 car.setRfid(value.toString()); 775 break; 776 case WAIT_COLUMN: 777 try { 778 car.setWait(Integer.parseInt(value.toString())); 779 } catch (NumberFormatException e) { 780 log.error("wait count must be a number"); 781 } 782 break; 783 default: 784 break; 785 } 786 } 787 788 public void dispose() { 789 carManager.removePropertyChangeListener(this); 790 removePropertyChangeCars(); 791 if (csf != null) { 792 csf.dispose(); 793 } 794 if (cef != null) { 795 cef.dispose(); 796 } 797 } 798 799 private void addPropertyChangeCars() { 800 for (Car car : carManager.getList()) { 801 car.addPropertyChangeListener(this); 802 } 803 } 804 805 private void removePropertyChangeCars() { 806 for (Car car : carManager.getList()) { 807 car.removePropertyChangeListener(this); 808 } 809 } 810 811 @Override 812 public void propertyChange(PropertyChangeEvent e) { 813 if (Control.SHOW_PROPERTY) { 814 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), 815 e.getNewValue()); 816 } 817 if (e.getPropertyName().equals(CarManager.LISTLENGTH_CHANGED_PROPERTY)) { 818 updateList(); 819 fireTableDataChanged(); 820 } // must be a car change 821 else if (e.getSource().getClass().equals(Car.class)) { 822 Car car = (Car) e.getSource(); 823 int row = carList.indexOf(car); 824 if (Control.SHOW_PROPERTY) { 825 log.debug("Update car table row: {}", row); 826 } 827 if (row >= 0) { 828 fireTableRowsUpdated(row, row); 829 // next is needed when only showing cars at a location or track 830 } else if (e.getPropertyName().equals(Car.TRACK_CHANGED_PROPERTY)) { 831 updateList(); 832 fireTableDataChanged(); 833 } 834 } 835 } 836 837 private static final Logger log = LoggerFactory.getLogger(CarsTableModel.class); 838}