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