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