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.jmrit.operations.trains.trainbuilder.TrainCommon; 021import jmri.util.swing.XTableColumnModel; 022import jmri.util.table.ButtonEditor; 023import jmri.util.table.ButtonRenderer; 024 025/** 026 * Table Model for edit of cars used by operations 027 * 028 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012, 2016 029 */ 030public class CarsTableModel extends OperationsTableModel implements PropertyChangeListener { 031 032 CarManager carManager = InstanceManager.getDefault(CarManager.class); // There is only one manager 033 034 // Defines the columns 035 private static final int SELECT_COLUMN = 0; 036 private static final int NUMBER_COLUMN = 1; 037 private static final int ROAD_COLUMN = 2; 038 private static final int TYPE_COLUMN = 3; 039 private static final int LENGTH_COLUMN = 4; 040 private static final int LOAD_COLUMN = 5; 041 private static final int RWE_LOAD_COLUMN = 6; 042 private static final int RWL_LOAD_COLUMN = 7; 043 private static final int COLOR_COLUMN = 8; 044 private static final int KERNEL_COLUMN = 9; 045 private static final int LOCATION_COLUMN = 10; 046 private static final int RFID_WHERE_LAST_SEEN_COLUMN = 11; 047 private static final int RFID_WHEN_LAST_SEEN_COLUMN = 12; 048 private static final int DESTINATION_COLUMN = 13; 049 private static final int FINAL_DESTINATION_COLUMN = 14; 050 private static final int RWE_DESTINATION_COLUMN = 15; 051 private static final int RWL_DESTINATION_COLUMN = 16; 052 private static final int ROUTE_COLUMN = 17; 053 private static final int LAST_LOCATION_COLUMN = 18; 054 private static final int DIVISION_COLUMN = 19; 055 private static final int TRAIN_COLUMN = 20; 056 private static final int LAST_TRAIN_COLUMN = 21; 057 private static final int MOVES_COLUMN = 22; 058 private static final int BUILT_COLUMN = 23; 059 private static final int OWNER_COLUMN = 24; 060 private static final int VALUE_COLUMN = 25; 061 private static final int RFID_COLUMN = 26; 062 private static final int WAIT_COLUMN = 27; 063 private static final int PICKUP_COLUMN = 28; 064 private static final int LAST_COLUMN = 29; 065 private static final int COMMENT_COLUMN = 30; 066 private static final int SET_COLUMN = 31; 067 private static final int EDIT_COLUMN = 32; 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(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 "Error"; // 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 public void toggleSelectVisible() { 256 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 257 tcm.setColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN), 258 !tcm.isColumnVisible(tcm.getColumnByModelIndex(SELECT_COLUMN))); 259 } 260 261 public void resetCheckboxes() { 262 for (Car car : carList) { 263 car.setSelected(false); 264 } 265 } 266 267 String _roadNumber = ""; 268 int _index = 0; 269 270 /** 271 * Search for car by road number 272 * 273 * @param roadNumber The string road number to search for. 274 * @return -1 if not found, table row number if found 275 */ 276 public int findCarByRoadNumber(String roadNumber) { 277 if (carList != null) { 278 if (!roadNumber.equals(_roadNumber)) { 279 return getIndex(0, roadNumber); 280 } 281 int index = getIndex(_index, roadNumber); 282 if (index > 0) { 283 return index; 284 } 285 return getIndex(0, roadNumber); 286 } 287 return -1; 288 } 289 290 private int getIndex(int start, String roadNumber) { 291 for (int index = start; index < carList.size(); index++) { 292 Car car = carList.get(index); 293 if (car != null) { 294 String[] number = car.getNumber().split(TrainCommon.HYPHEN); 295 // check for wild card '*' 296 if (roadNumber.startsWith("*") && roadNumber.endsWith("*")) { 297 String rN = roadNumber.substring(1, roadNumber.length() - 1); 298 if (car.getNumber().contains(rN)) { 299 _roadNumber = roadNumber; 300 _index = index + 1; 301 return index; 302 } 303 } else if (roadNumber.startsWith("*")) { 304 String rN = roadNumber.substring(1); 305 if (car.getNumber().endsWith(rN) || number[0].endsWith(rN)) { 306 _roadNumber = roadNumber; 307 _index = index + 1; 308 return index; 309 } 310 } else if (roadNumber.endsWith("*")) { 311 String rN = roadNumber.substring(0, roadNumber.length() - 1); 312 if (car.getNumber().startsWith(rN)) { 313 _roadNumber = roadNumber; 314 _index = index + 1; 315 return index; 316 } 317 } else if (car.getNumber().equals(roadNumber) || number[0].equals(roadNumber)) { 318 _roadNumber = roadNumber; 319 _index = index + 1; 320 return index; 321 } 322 } 323 } 324 _roadNumber = ""; 325 return -1; 326 } 327 328 public Car getCarAtIndex(int index) { 329 return carList.get(index); 330 } 331 332 private void updateList() { 333 // first, remove listeners from the individual objects 334 removePropertyChangeCars(); 335 carList = getSelectedCarList(); 336 // and add listeners back in 337 addPropertyChangeCars(); 338 } 339 340 public List<Car> getSelectedCarList() { 341 return getCarList(_sort); 342 } 343 344 @SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", justification = "default case is sort by number") // NOI18N 345 public List<Car> getCarList(int sort) { 346 List<Car> list; 347 switch (sort) { 348 case SORTBY_NUMBER: 349 list = carManager.getByNumberList(); 350 break; 351 case SORTBY_ROAD: 352 list = carManager.getByRoadNameList(); 353 break; 354 case SORTBY_TYPE: 355 list = carManager.getByTypeList(); 356 break; 357 case SORTBY_COLOR: 358 list = carManager.getByColorList(); 359 break; 360 case SORTBY_LOAD: 361 list = carManager.getByLoadList(); 362 break; 363 case SORTBY_KERNEL: 364 list = carManager.getByKernelList(); 365 break; 366 case SORTBY_LOCATION: 367 list = carManager.getByLocationList(); 368 break; 369 case SORTBY_DESTINATION: 370 list = carManager.getByDestinationList(); 371 break; 372 case SORTBY_TRAIN: 373 list = carManager.getByTrainList(); 374 break; 375 case SORTBY_FINALDESTINATION: 376 list = carManager.getByFinalDestinationList(); 377 break; 378 case SORTBY_RWE: 379 list = carManager.getByRweList(); 380 break; 381 case SORTBY_RWL: 382 list = carManager.getByRwlList(); 383 break; 384 case SORTBY_ROUTE: 385 list = carManager.getByRouteList(); 386 break; 387 case SORTBY_DIVISION: 388 list = carManager.getByDivisionList(); 389 break; 390 case SORTBY_MOVES: 391 list = carManager.getByMovesList(); 392 break; 393 case SORTBY_BUILT: 394 list = carManager.getByBuiltList(); 395 break; 396 case SORTBY_OWNER: 397 list = carManager.getByOwnerList(); 398 break; 399 case SORTBY_VALUE: 400 list = carManager.getByValueList(); 401 break; 402 case SORTBY_RFID: 403 list = carManager.getByRfidList(); 404 break; 405 case SORTBY_WAIT: 406 list = carManager.getByWaitList(); 407 break; 408 case SORTBY_PICKUP: 409 list = carManager.getByPickupList(); 410 break; 411 case SORTBY_LAST: 412 list = carManager.getByLastDateList(); 413 break; 414 case SORTBY_COMMENT: 415 list = carManager.getByCommentList(); 416 break; 417 default: 418 list = carManager.getByNumberList(); 419 } 420 filterList(list); 421 return list; 422 } 423 424 private void filterList(List<Car> list) { 425 if (showAllCars) { 426 return; 427 } 428 for (int i = 0; i < list.size(); i++) { 429 Car car = list.get(i); 430 if (car.getLocation() == null) { 431 list.remove(i--); 432 continue; 433 } 434 // filter out cars that don't have a location name that matches 435 if (locationName != null) { 436 if (!car.getLocationName().equals(locationName)) { 437 list.remove(i--); 438 continue; 439 } 440 if (trackName != null) { 441 if (!car.getTrackName().equals(trackName)) { 442 list.remove(i--); 443 } 444 } 445 } 446 } 447 } 448 449 void initTable(JTable table, CarsTableFrame frame) { 450 super.initTable(table); 451 _table = table; 452 _frame = frame; 453 initTable(); 454 } 455 456 // Cars frame table column widths, starts with Select column and ends with Edit 457 private final int[] tableColumnWidths = {60, 60, 60, 65, 35, 75, 75, 75, 75, 65, 190, 190, 140, 190, 190, 190, 190, 458 190, 190, 190, 65, 90, 50, 50, 50, 50, 100, 50, 100, 100, 100, 65, 70}; 459 460 void initTable() { 461 // Use XTableColumnModel so we can control which columns are visible 462 XTableColumnModel tcm = new XTableColumnModel(); 463 _table.setColumnModel(tcm); 464 _table.createDefaultColumnsFromModel(); 465 466 // Install the button handlers 467 ButtonRenderer buttonRenderer = new ButtonRenderer(); 468 tcm.getColumn(SET_COLUMN).setCellRenderer(buttonRenderer); 469 TableCellEditor buttonEditor = new ButtonEditor(new javax.swing.JButton()); 470 tcm.getColumn(SET_COLUMN).setCellEditor(buttonEditor); 471 tcm.getColumn(EDIT_COLUMN).setCellRenderer(buttonRenderer); 472 tcm.getColumn(EDIT_COLUMN).setCellEditor(buttonEditor); 473 474 // set column preferred widths 475 for (int i = 0; i < tcm.getColumnCount(); i++) { 476 tcm.getColumn(i).setPreferredWidth(tableColumnWidths[i]); 477 } 478 _frame.loadTableDetails(_table); 479 480 // turn off columns 481 tcm.setColumnVisible(tcm.getColumnByModelIndex(COLOR_COLUMN), false); 482 tcm.setColumnVisible(tcm.getColumnByModelIndex(FINAL_DESTINATION_COLUMN), false); 483 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_DESTINATION_COLUMN), false); 484 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWE_LOAD_COLUMN), false); 485 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_DESTINATION_COLUMN), false); 486 tcm.setColumnVisible(tcm.getColumnByModelIndex(RWL_LOAD_COLUMN), false); 487 tcm.setColumnVisible(tcm.getColumnByModelIndex(ROUTE_COLUMN), false); 488 tcm.setColumnVisible(tcm.getColumnByModelIndex(BUILT_COLUMN), false); 489 tcm.setColumnVisible(tcm.getColumnByModelIndex(OWNER_COLUMN), false); 490 tcm.setColumnVisible(tcm.getColumnByModelIndex(VALUE_COLUMN), false); 491 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_COLUMN), false); 492 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHEN_LAST_SEEN_COLUMN), false); 493 tcm.setColumnVisible(tcm.getColumnByModelIndex(RFID_WHERE_LAST_SEEN_COLUMN), false); 494 tcm.setColumnVisible(tcm.getColumnByModelIndex(WAIT_COLUMN), false); 495 tcm.setColumnVisible(tcm.getColumnByModelIndex(PICKUP_COLUMN), false); 496 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_LOCATION_COLUMN), false); 497 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_COLUMN), false); 498 tcm.setColumnVisible(tcm.getColumnByModelIndex(LAST_TRAIN_COLUMN), false); 499 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), false); 500 501 // turn on defaults 502 tcm.setColumnVisible(tcm.getColumnByModelIndex(LOAD_COLUMN), true); 503 tcm.setColumnVisible(tcm.getColumnByModelIndex(DESTINATION_COLUMN), true); 504 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), true); 505 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_COLUMN), true); 506 507 tcm.setColumnVisible(tcm.getColumnByModelIndex(DIVISION_COLUMN), carManager.isThereDivisions()); 508 } 509 510 @Override 511 public int getRowCount() { 512 return carList.size(); 513 } 514 515 @Override 516 public int getColumnCount() { 517 return HIGHESTCOLUMN; 518 } 519 520 @Override 521 public String getColumnName(int col) { 522 switch (col) { 523 case SELECT_COLUMN: 524 return Bundle.getMessage("ButtonSelect"); 525 case NUMBER_COLUMN: 526 return Bundle.getMessage("Number"); 527 case ROAD_COLUMN: 528 return Bundle.getMessage("Road"); 529 case LOAD_COLUMN: 530 return Bundle.getMessage("Load"); 531 case COLOR_COLUMN: 532 return Bundle.getMessage("Color"); 533 case TYPE_COLUMN: 534 return Bundle.getMessage("Type"); 535 case LENGTH_COLUMN: 536 return Bundle.getMessage("Len"); 537 case KERNEL_COLUMN: 538 return Bundle.getMessage("Kernel"); 539 case LOCATION_COLUMN: 540 return Bundle.getMessage("Location"); 541 case RFID_WHERE_LAST_SEEN_COLUMN: 542 return Bundle.getMessage("WhereLastSeen"); 543 case RFID_WHEN_LAST_SEEN_COLUMN: 544 return Bundle.getMessage("WhenLastSeen"); 545 case DESTINATION_COLUMN: 546 return Bundle.getMessage("Destination"); 547 case FINAL_DESTINATION_COLUMN: 548 return Bundle.getMessage("FinalDestination"); 549 case RWE_DESTINATION_COLUMN: 550 return Bundle.getMessage("RWELocation"); 551 case RWE_LOAD_COLUMN: 552 return Bundle.getMessage("RWELoad"); 553 case RWL_DESTINATION_COLUMN: 554 return Bundle.getMessage("RWLLocation"); 555 case RWL_LOAD_COLUMN: 556 return Bundle.getMessage("RWLLoad"); 557 case ROUTE_COLUMN: 558 return Bundle.getMessage("Route"); 559 case LAST_LOCATION_COLUMN: 560 return Bundle.getMessage("LastLocation"); 561 case DIVISION_COLUMN: 562 return Bundle.getMessage("HomeDivision"); 563 case TRAIN_COLUMN: 564 return Bundle.getMessage("Train"); 565 case LAST_TRAIN_COLUMN: 566 return Bundle.getMessage("LastTrain"); 567 case MOVES_COLUMN: 568 return Bundle.getMessage("Moves"); 569 case BUILT_COLUMN: 570 return Bundle.getMessage("Built"); 571 case OWNER_COLUMN: 572 return Bundle.getMessage("Owner"); 573 case VALUE_COLUMN: 574 return Setup.getValueLabel(); 575 case RFID_COLUMN: 576 return Setup.getRfidLabel(); 577 case WAIT_COLUMN: 578 return Bundle.getMessage("Wait"); 579 case PICKUP_COLUMN: 580 return Bundle.getMessage("Pickup"); 581 case LAST_COLUMN: 582 return Bundle.getMessage("LastMoved"); 583 case COMMENT_COLUMN: 584 return Bundle.getMessage("Comment"); 585 case SET_COLUMN: 586 return Bundle.getMessage("Set"); 587 case EDIT_COLUMN: 588 return Bundle.getMessage("ButtonEdit"); // titles above all columns 589 default: 590 return "unknown"; // NOI18N 591 } 592 } 593 594 @Override 595 public Class<?> getColumnClass(int col) { 596 switch (col) { 597 case SELECT_COLUMN: 598 return Boolean.class; 599 case SET_COLUMN: 600 case EDIT_COLUMN: 601 return JButton.class; 602 case LENGTH_COLUMN: 603 case MOVES_COLUMN: 604 case WAIT_COLUMN: 605 return Integer.class; 606 default: 607 return String.class; 608 } 609 } 610 611 @Override 612 public boolean isCellEditable(int row, int col) { 613 switch (col) { 614 case SELECT_COLUMN: 615 case SET_COLUMN: 616 case EDIT_COLUMN: 617 case MOVES_COLUMN: 618 case WAIT_COLUMN: 619 case VALUE_COLUMN: 620 case RFID_COLUMN: 621 return true; 622 default: 623 return false; 624 } 625 } 626 627 @Override 628 public Object getValueAt(int row, int col) { 629 if (row >= getRowCount()) { 630 return "ERROR row " + row; // NOI18N 631 } 632 Car car = carList.get(row); 633 if (car == null) { 634 return "ERROR car unknown " + row; // NOI18N 635 } 636 switch (col) { 637 case SELECT_COLUMN: 638 return car.isSelected(); 639 case NUMBER_COLUMN: 640 return car.getNumber(); 641 case ROAD_COLUMN: 642 return car.getRoadName(); 643 case LOAD_COLUMN: 644 return getLoadNameString(car); 645 case COLOR_COLUMN: 646 return car.getColor(); 647 case LENGTH_COLUMN: 648 return car.getLengthInteger(); 649 case TYPE_COLUMN: 650 return car.getTypeName() + car.getTypeExtensions(); 651 case KERNEL_COLUMN: 652 if (car.isLead()) { 653 return car.getKernelName() + "*"; 654 } 655 return car.getKernelName(); 656 case LOCATION_COLUMN: 657 if (car.getLocation() != null) { 658 return car.getStatus() + car.getLocationName() + " (" + car.getTrackName() + ")"; 659 } 660 return car.getStatus(); 661 case RFID_WHERE_LAST_SEEN_COLUMN: 662 return car.getWhereLastSeenName() + 663 (car.getTrackLastSeenName().equals(Car.NONE) ? "" : " (" + car.getTrackLastSeenName() + ")"); 664 case RFID_WHEN_LAST_SEEN_COLUMN: { 665 return car.getWhenLastSeenDate(); 666 } 667 case DESTINATION_COLUMN: 668 case FINAL_DESTINATION_COLUMN: { 669 String s = ""; 670 if (car.getDestination() != null) { 671 s = car.getDestinationName() + " (" + car.getDestinationTrackName() + ")"; 672 } 673 if (car.getFinalDestination() != null) { 674 s = s + "->" + car.getFinalDestinationName(); // NOI18N 675 } 676 if (car.getFinalDestinationTrack() != null) { 677 s = s + " (" + car.getFinalDestinationTrackName() + ")"; 678 } 679 if (log.isDebugEnabled() && 680 car.getFinalDestinationTrack() != null && 681 car.getFinalDestinationTrack().getSchedule() != null) { 682 s = s + " " + car.getScheduleItemId(); 683 } 684 return s; 685 } 686 case RWE_DESTINATION_COLUMN: { 687 String s = car.getReturnWhenEmptyDestinationName(); 688 if (car.getReturnWhenEmptyDestTrack() != null) { 689 s = s + " (" + car.getReturnWhenEmptyDestTrackName() + ")"; 690 } 691 return s; 692 } 693 case RWE_LOAD_COLUMN: 694 return car.getReturnWhenEmptyLoadName(); 695 case RWL_DESTINATION_COLUMN: { 696 String s = car.getReturnWhenLoadedDestinationName(); 697 if (car.getReturnWhenLoadedDestTrack() != null) { 698 s = s + " (" + car.getReturnWhenLoadedDestTrackName() + ")"; 699 } 700 return s; 701 } 702 case RWL_LOAD_COLUMN: 703 return car.getReturnWhenLoadedLoadName(); 704 case ROUTE_COLUMN: 705 return car.getRoutePath(); 706 case DIVISION_COLUMN: 707 return car.getDivisionName(); 708 case LAST_LOCATION_COLUMN: { 709 String s = ""; 710 if (!car.getLastLocationName().equals(Car.NONE)) { 711 s = car.getLastLocationName() + " (" + car.getLastTrackName() + ")"; 712 } 713 return s; 714 } 715 case TRAIN_COLUMN: { 716 // if train was manually set by user add an asterisk 717 if (car.getTrain() != null && car.getRouteLocation() == null) { 718 return car.getTrainName() + "*"; 719 } 720 return car.getTrainName(); 721 } 722 case LAST_TRAIN_COLUMN: 723 return car.getLastTrainName(); 724 case MOVES_COLUMN: 725 return car.getMoves(); 726 case BUILT_COLUMN: 727 return car.getBuilt(); 728 case OWNER_COLUMN: 729 return car.getOwnerName(); 730 case VALUE_COLUMN: 731 return car.getValue(); 732 case RFID_COLUMN: 733 return car.getRfid(); 734 case WAIT_COLUMN: 735 return car.getWait(); 736 case PICKUP_COLUMN: 737 return car.getPickupScheduleName(); 738 case LAST_COLUMN: 739 return car.getSortDate(); 740 case COMMENT_COLUMN: 741 return car.getComment(); 742 case SET_COLUMN: 743 return Bundle.getMessage("Set"); 744 case EDIT_COLUMN: 745 return Bundle.getMessage("ButtonEdit"); 746 default: 747 return "unknown " + col; // NOI18N 748 } 749 } 750 751 private String getLoadNameString(Car car) { 752 StringBuffer sb = new StringBuffer(car.getLoadName()); 753 if (car.getLoadPriority().equals(CarLoad.PRIORITY_HIGH)) { 754 sb.append(" " + Bundle.getMessage("(P)")); 755 } else if (car.getLoadPriority().equals(CarLoad.PRIORITY_MEDIUM)) { 756 sb.append(" " + Bundle.getMessage("(M)")); 757 } 758 if (car.isCarLoadHazardous()) { 759 sb.append(" " + Bundle.getMessage("(H)")); 760 } 761 return sb.toString(); 762 } 763 764 CarEditFrame cef = null; 765 CarSetFrame csf = null; 766 767 @Override 768 public void setValueAt(Object value, int row, int col) { 769 Car car = carList.get(row); 770 switch (col) { 771 case SELECT_COLUMN: 772 car.setSelected(((Boolean) value).booleanValue()); 773 break; 774 case SET_COLUMN: 775 log.debug("Set car"); 776 if (csf != null) { 777 csf.dispose(); 778 } 779 // use invokeLater so new window appears on top 780 SwingUtilities.invokeLater(() -> { 781 csf = new CarSetFrame(); 782 csf.initComponents(); 783 csf.load(car); 784 }); 785 break; 786 case EDIT_COLUMN: 787 log.debug("Edit car"); 788 if (cef != null) { 789 cef.dispose(); 790 } 791 // use invokeLater so new window appears on top 792 SwingUtilities.invokeLater(() -> { 793 cef = new CarEditFrame(); 794 cef.initComponents(); 795 cef.load(car); 796 }); 797 break; 798 case MOVES_COLUMN: 799 try { 800 car.setMoves(Integer.parseInt(value.toString())); 801 } catch (NumberFormatException e) { 802 log.error("move count must be a number"); 803 } 804 break; 805 case VALUE_COLUMN: 806 car.setValue(value.toString()); 807 break; 808 case RFID_COLUMN: 809 car.setRfid(value.toString()); 810 break; 811 case WAIT_COLUMN: 812 try { 813 car.setWait(Integer.parseInt(value.toString())); 814 } catch (NumberFormatException e) { 815 log.error("wait count must be a number"); 816 } 817 break; 818 default: 819 break; 820 } 821 } 822 823 public void dispose() { 824 carManager.removePropertyChangeListener(this); 825 removePropertyChangeCars(); 826 if (csf != null) { 827 csf.dispose(); 828 } 829 if (cef != null) { 830 cef.dispose(); 831 } 832 } 833 834 private void addPropertyChangeCars() { 835 for (Car car : carManager.getList()) { 836 car.addPropertyChangeListener(this); 837 } 838 } 839 840 private void removePropertyChangeCars() { 841 for (Car car : carManager.getList()) { 842 car.removePropertyChangeListener(this); 843 } 844 } 845 846 @Override 847 public void propertyChange(PropertyChangeEvent e) { 848 if (Control.SHOW_PROPERTY) { 849 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), 850 e.getNewValue()); 851 } 852 if (e.getPropertyName().equals(CarManager.LISTLENGTH_CHANGED_PROPERTY)) { 853 updateList(); 854 fireTableDataChanged(); 855 } // must be a car change 856 else if (e.getSource().getClass().equals(Car.class)) { 857 Car car = (Car) e.getSource(); 858 int row = carList.indexOf(car); 859 if (Control.SHOW_PROPERTY) { 860 log.debug("Update car table row: {}", row); 861 } 862 if (row >= 0) { 863 fireTableRowsUpdated(row, row); 864 // next is needed when only showing cars at a location or track 865 } else if (e.getPropertyName().equals(Car.TRACK_CHANGED_PROPERTY)) { 866 updateList(); 867 fireTableDataChanged(); 868 } 869 } 870 } 871 872 private final static Logger log = LoggerFactory.getLogger(CarsTableModel.class); 873}