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