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