001package jmri.jmrit.operations.locations.gui; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.util.*; 006 007import javax.swing.*; 008import javax.swing.event.*; 009import javax.swing.table.TableColumn; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014import jmri.InstanceManager; 015import jmri.jmrit.operations.OperationsPanel; 016import jmri.jmrit.operations.OperationsTableModel; 017import jmri.jmrit.operations.locations.*; 018import jmri.jmrit.operations.locations.tools.TrackEditCommentsFrame; 019import jmri.jmrit.operations.setup.Control; 020import jmri.jmrit.operations.setup.Setup; 021import jmri.util.swing.XTableColumnModel; 022import jmri.util.table.ButtonEditor; 023import jmri.util.table.ButtonRenderer; 024 025/** 026 * Table Model for edit of tracks used by operations 027 * 028 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012 029 */ 030public abstract class TrackTableModel extends OperationsTableModel implements PropertyChangeListener, TableColumnModelListener { 031 032 protected Location _location; 033 protected List<Track> _tracksList = new ArrayList<>(); 034 protected String _trackType; 035 protected JTable _table; 036 protected boolean _dirty = false; 037 038 // Defines the columns 039 protected static final int ID_COLUMN = 0; 040 protected static final int NAME_COLUMN = 1; 041 protected static final int LENGTH_COLUMN = 2; 042 protected static final int USED_LENGTH_COLUMN = 3; 043 protected static final int RESERVED_COLUMN = 4; 044 protected static final int MOVES_COLUMN = 5; 045 protected static final int CARS_COLUMN = 6; 046 protected static final int LOCOS_COLUMN = 7; 047 protected static final int PICKUPS_COLUMN = 8; 048 protected static final int SETOUT_COLUMN = 9; 049 protected static final int SCHEDULE_COLUMN = 10; 050 protected static final int ROAD_COLUMN = 11; 051 protected static final int LOAD_COLUMN = 12; 052 protected static final int DEFAULT_LOAD_COLUMN = 13; 053 protected static final int CUSTOM_LOAD_COLUMN = 14; 054 protected static final int DISABLE_LOAD_CHANGE_COLUMN = 15; 055 protected static final int QUICK_SERVICE_COLUMN = 16; 056 protected static final int SHIP_COLUMN = 17; 057 protected static final int RESTRICTION_COLUMN = 18; 058 protected static final int DESTINATION_COLUMN = 19; 059 protected static final int ROUTED_COLUMN = 20; 060 protected static final int HOLD_COLUMN = 21; 061 protected static final int POOL_COLUMN = 22; 062 protected static final int PLANPICKUP_COLUMN = 23; 063 protected static final int ALT_TRACK_COLUMN = 24; 064 protected static final int ORDER_COLUMN = 25; 065 protected static final int TRAIN_DIRECTION_COLUMN = 26; 066 protected static final int REPORTER_COLUMN = 27; 067 protected static final int COMMENT_COLUMN = 28; 068 protected static final int EDIT_COLUMN = 29; 069 070 protected static final int HIGHESTCOLUMN = EDIT_COLUMN + 1; 071 072 public TrackTableModel() { 073 super(); 074 } 075 076 protected void initTable(JTable table, Location location, String trackType) { 077 _table = table; 078 _location = location; 079 _trackType = trackType; 080 if (_location != null) { 081 _location.addPropertyChangeListener(this); 082 } 083 Setup.getDefault().addPropertyChangeListener(this); 084 updateList(); 085 initTable(); 086 } 087 088 private void updateList() { 089 if (_location == null) { 090 return; 091 } 092 // first, remove listeners from the individual objects 093 removePropertyChangeTracks(); 094 095 _tracksList = _location.getTracksByNameList(_trackType); 096 // and add them back in 097 for (Track track : _tracksList) { 098 track.addPropertyChangeListener(this); 099 } 100 } 101 102 private void initTable() { 103 // Use XTableColumnModel so we can control which columns are visible 104 XTableColumnModel tcm = new XTableColumnModel(); 105 _table.setColumnModel(tcm); 106 _table.createDefaultColumnsFromModel(); 107 108 // set column preferred widths 109 tcm.getColumn(ID_COLUMN).setPreferredWidth(40); 110 tcm.getColumn(NAME_COLUMN).setPreferredWidth(200); 111 tcm.getColumn(LENGTH_COLUMN).setPreferredWidth( 112 Math.max(50, new JLabel(getColumnName(LENGTH_COLUMN)).getPreferredSize().width + 10)); 113 tcm.getColumn(USED_LENGTH_COLUMN).setPreferredWidth(50); 114 tcm.getColumn(RESERVED_COLUMN).setPreferredWidth( 115 Math.max(65, new JLabel(getColumnName(RESERVED_COLUMN)).getPreferredSize().width + 10)); 116 tcm.getColumn(MOVES_COLUMN).setPreferredWidth(60); 117 tcm.getColumn(LOCOS_COLUMN).setPreferredWidth(60); 118 tcm.getColumn(CARS_COLUMN).setPreferredWidth(60); 119 tcm.getColumn(PICKUPS_COLUMN).setPreferredWidth( 120 Math.max(60, new JLabel(getColumnName(PICKUPS_COLUMN)).getPreferredSize().width + 10)); 121 tcm.getColumn(SETOUT_COLUMN).setPreferredWidth( 122 Math.max(60, new JLabel(getColumnName(SETOUT_COLUMN)).getPreferredSize().width + 10)); 123 tcm.getColumn(SCHEDULE_COLUMN).setPreferredWidth( 124 Math.max(90, new JLabel(getColumnName(SCHEDULE_COLUMN)).getPreferredSize().width + 10)); 125 tcm.getColumn(RESTRICTION_COLUMN).setPreferredWidth(90); 126 tcm.getColumn(LOAD_COLUMN).setPreferredWidth(50); 127 tcm.getColumn(DEFAULT_LOAD_COLUMN).setPreferredWidth(60); 128 tcm.getColumn(CUSTOM_LOAD_COLUMN).setPreferredWidth(90); 129 tcm.getColumn(DISABLE_LOAD_CHANGE_COLUMN).setPreferredWidth(50); 130 tcm.getColumn(QUICK_SERVICE_COLUMN).setPreferredWidth(50); 131 tcm.getColumn(SHIP_COLUMN).setPreferredWidth(50); 132 tcm.getColumn(ROAD_COLUMN).setPreferredWidth(50); 133 tcm.getColumn(DESTINATION_COLUMN).setPreferredWidth(50); 134 tcm.getColumn(ROUTED_COLUMN).setPreferredWidth(50); 135 tcm.getColumn(HOLD_COLUMN).setPreferredWidth(50); 136 tcm.getColumn(POOL_COLUMN).setPreferredWidth(70); 137 tcm.getColumn(PLANPICKUP_COLUMN).setPreferredWidth(70); 138 tcm.getColumn(ALT_TRACK_COLUMN).setPreferredWidth(120); 139 tcm.getColumn(ORDER_COLUMN) 140 .setPreferredWidth(Math.max(50, new JLabel(getColumnName(ORDER_COLUMN)).getPreferredSize().width + 10)); 141 tcm.getColumn(TRAIN_DIRECTION_COLUMN).setPreferredWidth(30); 142 tcm.getColumn(REPORTER_COLUMN).setPreferredWidth(70); 143 tcm.getColumn(COMMENT_COLUMN).setPreferredWidth(80); 144 tcm.getColumn(EDIT_COLUMN).setPreferredWidth(80); 145 146 tcm.getColumn(COMMENT_COLUMN).setCellRenderer(new ButtonRenderer()); 147 tcm.getColumn(COMMENT_COLUMN).setCellEditor(new ButtonEditor(new JButton())); 148 tcm.getColumn(EDIT_COLUMN).setCellRenderer(new ButtonRenderer()); 149 tcm.getColumn(EDIT_COLUMN).setCellEditor(new ButtonEditor(new JButton())); 150 151 OperationsPanel.loadTableDetails(_table, "Location"); 152 setColumnsVisible(); 153 addTableColumnListeners(); 154 } 155 156 // only show columns if they are needed 157 private void setColumnsVisible() { 158 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 159 tcm.setColumnVisible(tcm.getColumnByModelIndex(ID_COLUMN), 160 InstanceManager.getDefault(LocationManager.class).isShowIdEnabled()); 161 tcm.setColumnVisible(tcm.getColumnByModelIndex(SCHEDULE_COLUMN), 162 _location.hasSchedules() && _trackType.equals(Track.SPUR)); 163 tcm.setColumnVisible(tcm.getColumnByModelIndex(RESTRICTION_COLUMN), 164 _location.hasServiceRestrictions() && !_trackType.equals(Track.YARD)); 165 tcm.setColumnVisible(tcm.getColumnByModelIndex(LOAD_COLUMN), _location.hasLoadRestrictions()); 166 tcm.setColumnVisible(tcm.getColumnByModelIndex(DEFAULT_LOAD_COLUMN), _trackType.equals(Track.STAGING)); 167 tcm.setColumnVisible(tcm.getColumnByModelIndex(CUSTOM_LOAD_COLUMN), _trackType.equals(Track.STAGING)); 168 tcm.setColumnVisible(tcm.getColumnByModelIndex(DISABLE_LOAD_CHANGE_COLUMN), 169 _location.hasDisableLoadChange() && _trackType.equals(Track.SPUR)); 170 tcm.setColumnVisible(tcm.getColumnByModelIndex(QUICK_SERVICE_COLUMN), 171 _location.hasQuickLoadService() && _trackType.equals(Track.SPUR)); 172 tcm.setColumnVisible(tcm.getColumnByModelIndex(SHIP_COLUMN), _location.hasShipLoadRestrictions()); 173 tcm.setColumnVisible(tcm.getColumnByModelIndex(ROAD_COLUMN), _location.hasRoadRestrictions()); 174 tcm.setColumnVisible(tcm.getColumnByModelIndex(DESTINATION_COLUMN), _location.hasDestinationRestrictions() && 175 (_trackType.equals(Track.INTERCHANGE) || _trackType.equals(Track.STAGING))); 176 tcm.setColumnVisible(tcm.getColumnByModelIndex(ROUTED_COLUMN), _trackType.equals(Track.INTERCHANGE) || 177 _trackType.equals(Track.STAGING)); 178 tcm.setColumnVisible(tcm.getColumnByModelIndex(HOLD_COLUMN), 179 _location.hasSchedules() && _location.hasAlternateTracks() && _trackType.equals(Track.SPUR)); 180 tcm.setColumnVisible(tcm.getColumnByModelIndex(PLANPICKUP_COLUMN), _location.hasPlannedPickups()); 181 tcm.setColumnVisible(tcm.getColumnByModelIndex(POOL_COLUMN), _location.hasPools()); 182 tcm.setColumnVisible(tcm.getColumnByModelIndex(ALT_TRACK_COLUMN), _location.hasAlternateTracks()); 183 tcm.setColumnVisible(tcm.getColumnByModelIndex(ORDER_COLUMN), 184 _location.hasOrderRestrictions() && !_trackType.equals(Track.SPUR)); 185 tcm.setColumnVisible(tcm.getColumnByModelIndex(TRAIN_DIRECTION_COLUMN), 186 _location.hasTracksWithRestrictedTrainDirections()); 187 tcm.setColumnVisible(tcm.getColumnByModelIndex(REPORTER_COLUMN), 188 Setup.isRfidEnabled() && _location.hasReporters()); 189 tcm.setColumnVisible(tcm.getColumnByModelIndex(MOVES_COLUMN), Setup.isShowTrackMovesEnabled()); 190 tcm.setColumnVisible(tcm.getColumnByModelIndex(COMMENT_COLUMN), _location.hasTrackMessages()); 191 } 192 193 /* 194 * Persisting using JmriJTablePersistenceManager doesn't quite work since 195 * the same table name is used for each track type; spur, yard, interchange, 196 * and staging. Plus multiple edit locations can be open at the same time, 197 * again using the same table name. The goal is to have a single change 198 * affect every table for all edit locations. Therefore any changes to 199 * column width or position is saved when the edit location window is 200 * closed. 201 */ 202 private void addTableColumnListeners() { 203 Enumeration<TableColumn> e = _table.getColumnModel().getColumns(); 204 while (e.hasMoreElements()) { 205 TableColumn column = e.nextElement(); 206 column.addPropertyChangeListener(this); 207 } 208 _table.getColumnModel().addColumnModelListener(this); 209 } 210 211 /** 212 * Table is dirty when a column is moved or width is changed. 213 * 214 * @param dirty set true if dirty 215 */ 216 private void setDirty(boolean dirty) { 217 _dirty = dirty; 218 } 219 220 private boolean isDirty() { 221 return _dirty; 222 } 223 224 @Override 225 public int getRowCount() { 226 return _tracksList.size(); 227 } 228 229 @Override 230 public int getColumnCount() { 231 return HIGHESTCOLUMN; 232 } 233 234 @Override 235 public String getColumnName(int col) { 236 switch (col) { 237 case ID_COLUMN: 238 return Bundle.getMessage("Id"); 239 case NAME_COLUMN: 240 return Bundle.getMessage("TrackName"); 241 case LENGTH_COLUMN: 242 return Bundle.getMessage("Length"); 243 case USED_LENGTH_COLUMN: 244 return Bundle.getMessage("Used"); 245 case RESERVED_COLUMN: 246 return Bundle.getMessage("Reserved"); 247 case MOVES_COLUMN: 248 return Bundle.getMessage("Moves"); 249 case LOCOS_COLUMN: 250 return Bundle.getMessage("Engines"); 251 case CARS_COLUMN: 252 return Bundle.getMessage("Cars"); 253 case PICKUPS_COLUMN: 254 return Bundle.getMessage("Pickups"); 255 case SETOUT_COLUMN: 256 return Bundle.getMessage("Drop"); 257 case SCHEDULE_COLUMN: 258 return Bundle.getMessage("Schedule"); 259 case RESTRICTION_COLUMN: 260 return Bundle.getMessage("Restrictions"); 261 case LOAD_COLUMN: 262 return Bundle.getMessage("Load"); 263 case DEFAULT_LOAD_COLUMN: 264 return Bundle.getMessage("LoadDefaultAbv"); 265 case CUSTOM_LOAD_COLUMN: 266 return Bundle.getMessage("LoadCustomAbv"); 267 case DISABLE_LOAD_CHANGE_COLUMN: 268 return Bundle.getMessage("DisableLoadChange"); 269 case QUICK_SERVICE_COLUMN: 270 return Bundle.getMessage("QuickLoadService"); 271 case SHIP_COLUMN: 272 return Bundle.getMessage("Ship"); 273 case ROAD_COLUMN: 274 return Bundle.getMessage("Road"); 275 case DESTINATION_COLUMN: 276 return Bundle.getMessage("Dest"); 277 case ROUTED_COLUMN: 278 return Bundle.getMessage("Routed"); 279 case HOLD_COLUMN: 280 return Bundle.getMessage("Hold"); 281 case POOL_COLUMN: 282 return Bundle.getMessage("Pool"); 283 case PLANPICKUP_COLUMN: 284 return Bundle.getMessage("PlanPickUp"); 285 case ALT_TRACK_COLUMN: 286 return Bundle.getMessage("AlternateTrack"); 287 case ORDER_COLUMN: 288 return Bundle.getMessage("ServiceOrder"); 289 case TRAIN_DIRECTION_COLUMN: 290 return Bundle.getMessage("AbbrevationDirection"); 291 case REPORTER_COLUMN: 292 return Bundle.getMessage("Reporters"); 293 case COMMENT_COLUMN: 294 return Bundle.getMessage("Comment"); 295 case EDIT_COLUMN: 296 return Bundle.getMessage("ButtonEdit"); 297 default: 298 return "unknown"; // NOI18N 299 } 300 } 301 302 @Override 303 public Class<?> getColumnClass(int col) { 304 switch (col) { 305 case ID_COLUMN: 306 case NAME_COLUMN: 307 case SCHEDULE_COLUMN: 308 case RESTRICTION_COLUMN: 309 case LOAD_COLUMN: 310 case DEFAULT_LOAD_COLUMN: 311 case CUSTOM_LOAD_COLUMN: 312 case SHIP_COLUMN: 313 case ROAD_COLUMN: 314 case DESTINATION_COLUMN: 315 case POOL_COLUMN: 316 case PLANPICKUP_COLUMN: 317 case ALT_TRACK_COLUMN: 318 case ORDER_COLUMN: 319 case TRAIN_DIRECTION_COLUMN: 320 case REPORTER_COLUMN: 321 return String.class; 322 case LENGTH_COLUMN: 323 case USED_LENGTH_COLUMN: 324 case RESERVED_COLUMN: 325 case MOVES_COLUMN: 326 case LOCOS_COLUMN: 327 case CARS_COLUMN: 328 case PICKUPS_COLUMN: 329 case SETOUT_COLUMN: 330 return Integer.class; 331 case COMMENT_COLUMN: 332 case EDIT_COLUMN: 333 return JButton.class; 334 case DISABLE_LOAD_CHANGE_COLUMN: 335 case QUICK_SERVICE_COLUMN: 336 case ROUTED_COLUMN: 337 case HOLD_COLUMN: 338 return Boolean.class; 339 default: 340 return null; 341 } 342 } 343 344 @Override 345 public boolean isCellEditable(int row, int col) { 346 switch (col) { 347 case MOVES_COLUMN: 348 case DISABLE_LOAD_CHANGE_COLUMN: 349 case QUICK_SERVICE_COLUMN: 350 case ROUTED_COLUMN: 351 case COMMENT_COLUMN: 352 case EDIT_COLUMN: 353 return true; 354 case HOLD_COLUMN: 355 return isHoldCarEnabled(row); 356 default: 357 return false; 358 } 359 } 360 361 private boolean isHoldCarEnabled(int row) { 362 Track track = _tracksList.get(row); 363 return track.getAlternateTrack() != null && track.getSchedule() != null; 364 } 365 366 @Override 367 public Object getValueAt(int row, int col) { 368 if (row >= getRowCount()) { 369 return "ERROR row " + row; // NOI18N 370 } 371 Track track = _tracksList.get(row); 372 if (track == null) { 373 return "ERROR track unknown " + row; // NOI18N 374 } 375 switch (col) { 376 case ID_COLUMN: 377 return track.getId(); 378 case NAME_COLUMN: 379 return track.getName(); 380 case LENGTH_COLUMN: 381 return track.getLength(); 382 case USED_LENGTH_COLUMN: 383 return track.getUsedLength(); 384 case RESERVED_COLUMN: 385 return track.getReserved(); 386 case MOVES_COLUMN: 387 return track.getMoves(); 388 case LOCOS_COLUMN: 389 return track.getNumberEngines(); 390 case CARS_COLUMN: 391 return track.getNumberCars(); 392 case PICKUPS_COLUMN: 393 return track.getPickupRS(); 394 case SETOUT_COLUMN: 395 return track.getDropRS(); 396 case SCHEDULE_COLUMN: 397 return track.getScheduleName(); 398 case RESTRICTION_COLUMN: 399 return getRestrictions(track); 400 case LOAD_COLUMN: 401 return getModifiedString(track.getLoadNames().length, track.getLoadOption().equals(Track.ALL_LOADS), 402 track.getLoadOption().equals(Track.INCLUDE_LOADS)); 403 case DEFAULT_LOAD_COLUMN: 404 return getDefaultLoadString(track); 405 case CUSTOM_LOAD_COLUMN: 406 return getCustomLoadString(track); 407 case DISABLE_LOAD_CHANGE_COLUMN: 408 return track.isDisableLoadChangeEnabled(); 409 case QUICK_SERVICE_COLUMN: 410 return track.isQuickServiceEnabled(); 411 case SHIP_COLUMN: 412 return getModifiedString(track.getShipLoadNames().length, 413 track.getShipLoadOption().equals(Track.ALL_LOADS), 414 track.getShipLoadOption().equals(Track.INCLUDE_LOADS)); 415 case ROAD_COLUMN: 416 return getModifiedString(track.getRoadNames().length, track.getRoadOption().equals(Track.ALL_ROADS), 417 track.getRoadOption().equals(Track.INCLUDE_ROADS)); 418 case DESTINATION_COLUMN: { 419 return getDestinationString(track); 420 } 421 case ROUTED_COLUMN: 422 return track.isOnlyCarsWithFinalDestinationEnabled(); 423 case HOLD_COLUMN: 424 return track.isHoldCarsWithCustomLoadsEnabled(); 425 case POOL_COLUMN: 426 return track.getPoolName(); 427 case PLANPICKUP_COLUMN: 428 if (track.getIgnoreUsedLengthPercentage() > Track.IGNORE_0) { 429 return track.getIgnoreUsedLengthPercentage() + "%"; 430 } 431 return ""; 432 case ALT_TRACK_COLUMN: 433 if (track.getAlternateTrack() != null) { 434 return track.getAlternateTrack().getName(); 435 } 436 if (track.isAlternate()) { 437 return Bundle.getMessage("ButtonYes"); 438 } 439 return ""; 440 case ORDER_COLUMN: 441 return track.getServiceOrder(); 442 case TRAIN_DIRECTION_COLUMN: 443 return getDirection(track); 444 case REPORTER_COLUMN: 445 return track.getReporterName(); 446 case COMMENT_COLUMN: 447 if (track.hasMessages()) { 448 return Bundle.getMessage("ButtonEdit"); 449 } 450 return Bundle.getMessage("Add"); 451 case EDIT_COLUMN: 452 return Bundle.getMessage("ButtonEdit"); 453 default: 454 return "unknown " + col; // NOI18N 455 } 456 } 457 458 private String getRestrictions(Track track) { 459 StringBuffer restrictions = new StringBuffer(); 460 if (!track.getDropOption().equals(Track.ANY)) { 461 String suffix = " "; 462 if (track.getDropOption().equals(Track.EXCLUDE_ROUTES) || 463 track.getDropOption().equals(Track.EXCLUDE_TRAINS)) { 464 suffix = "x"; 465 } 466 restrictions.append(Bundle.getMessage("AbbreviationSetOut") + suffix + track.getDropIds().length); 467 } 468 if (!track.getPickupOption().equals(Track.ANY)) { 469 String suffix = " "; 470 if (track.getPickupOption().equals(Track.EXCLUDE_ROUTES) || 471 track.getPickupOption().equals(Track.EXCLUDE_TRAINS)) { 472 suffix = "x"; 473 } 474 restrictions.append(" " + Bundle.getMessage("AbbreviationPickUp") + suffix + track.getPickupIds().length); 475 } 476 return restrictions.toString(); 477 } 478 479 private String getModifiedString(int number, boolean all, boolean accept) { 480 if (all) { 481 return ""; 482 } 483 if (accept) { 484 return "A " + Integer.toString(number); // NOI18N 485 } 486 return "E " + Integer.toString(number); // NOI18N 487 } 488 489 private String getDefaultLoadString(Track track) { 490 String defaultLoad = ""; 491 if (track.isLoadSwapEnabled()) { 492 defaultLoad = Bundle.getMessage("ABV_SwapDefaultLoads"); 493 } 494 if (track.isLoadEmptyEnabled()) { 495 defaultLoad = Bundle.getMessage("ABV_EmptyDefaultLoads"); 496 } 497 return defaultLoad; 498 } 499 500 private String getCustomLoadString(Track track) { 501 StringBuffer customLoad = new StringBuffer(); 502 if (track.isRemoveCustomLoadsEnabled()) { 503 customLoad.append(Bundle.getMessage("ABV_EmptyCustomLoads") + " "); 504 } 505 if (track.isAddCustomLoadsEnabled()) { 506 customLoad.append(Bundle.getMessage("ABV_GenerateCustomLoad") + " "); 507 } 508 if (track.isAddCustomLoadsAnySpurEnabled()) { 509 customLoad.append(Bundle.getMessage("ABV_GenerateCustomLoadAnySpur") + " "); 510 } 511 if (track.isAddCustomLoadsAnyStagingTrackEnabled()) { 512 customLoad.append(Bundle.getMessage("ABV_GereateCustomLoadStaging")); 513 } 514 if (track.isBlockCarsEnabled()) { 515 customLoad.append(Bundle.getMessage("ABV_CarBlocking")); 516 } 517 return customLoad.toString(); 518 } 519 520 private String getDestinationString(Track track) { 521 int size = track.getDestinationListSize(); 522 if (track.getDestinationOption().equals(Track.EXCLUDE_DESTINATIONS)) { 523 size = InstanceManager.getDefault(LocationManager.class).getNumberOfLocations() - size; 524 } else if (size == 1 && track.getDestinationOption().equals(Track.INCLUDE_DESTINATIONS)) { 525 // if there's only one destination return the destination name 526 Location loc = 527 InstanceManager.getDefault(LocationManager.class).getLocationById(track.getDestinationIds()[0]); 528 if (loc != null) { 529 return loc.getName(); 530 } 531 } 532 return getModifiedString(size, track.getDestinationOption().equals(Track.ALL_DESTINATIONS), 533 track.getDestinationOption().equals(Track.INCLUDE_DESTINATIONS)); 534 } 535 536 private String getDirection(Track track) { 537 int trainDirections = track.getLocation().getTrainDirections() & Setup.getTrainDirection(); 538 if (trainDirections != (track.getTrainDirections() & trainDirections)) { 539 switch (track.getTrainDirections() & trainDirections) { 540 case Track.EAST: 541 return Setup.EAST_DIR; 542 case Track.WEST: 543 return Setup.WEST_DIR; 544 case Track.SOUTH: 545 return Setup.SOUTH_DIR; 546 case Track.NORTH: 547 return Setup.NORTH_DIR; 548 case 0: 549 return Bundle.getMessage("None"); 550 default: 551 return "X"; 552 } 553 } 554 return ""; 555 } 556 557 @Override 558 public void setValueAt(Object value, int row, int col) { 559 switch (col) { 560 case DISABLE_LOAD_CHANGE_COLUMN: 561 setDisableLoadChange(row, value); 562 break; 563 case QUICK_SERVICE_COLUMN: 564 setQuickService(row, value); 565 break; 566 case ROUTED_COLUMN: 567 setRouted(row, value); 568 break; 569 case HOLD_COLUMN: 570 setHold(row, value); 571 break; 572 case COMMENT_COLUMN: 573 trackComment(row); 574 break; 575 case EDIT_COLUMN: 576 editTrack(row); 577 break; 578 case MOVES_COLUMN: 579 setMoves(row, value); 580 break; 581 default: 582 break; 583 } 584 } 585 586 TrackEditFrame tef = null; 587 588 abstract protected void editTrack(int row); 589 590 private void setDisableLoadChange(int row, Object value) { 591 Track track = _tracksList.get(row); 592 track.setDisableLoadChangeEnabled(((Boolean) value).booleanValue()); 593 } 594 595 private void setQuickService(int row, Object value) { 596 Track track = _tracksList.get(row); 597 track.setQuickServiceEnabled(((Boolean) value).booleanValue()); 598 } 599 600 private void setRouted(int row, Object value) { 601 Track track = _tracksList.get(row); 602 track.setOnlyCarsWithFinalDestinationEnabled(((Boolean) value).booleanValue()); 603 } 604 605 private void setHold(int row, Object value) { 606 Track track = _tracksList.get(row); 607 track.setHoldCarsWithCustomLoadsEnabled(((Boolean) value).booleanValue()); 608 } 609 610 private void setMoves(int row, Object value) { 611 Track track = _tracksList.get(row); 612 track.setMoves((int) value); 613 } 614 615 private void trackComment(int row) { 616 new TrackEditCommentsFrame(_tracksList.get(row)); 617 } 618 619 private void removePropertyChangeTracks() { 620 for (Track track : _tracksList) { 621 track.removePropertyChangeListener(this); 622 } 623 } 624 625 public void dispose() { 626 if (_table != null) { 627 _table.getRowSorter().setSortKeys(null); 628 if (isDirty()) { 629 OperationsPanel.cacheState(_table); 630 OperationsPanel.saveTableState(); 631 setDirty(false); 632 } 633 } 634 removePropertyChangeTracks(); 635 if (_location != null) { 636 _location.removePropertyChangeListener(this); 637 } 638 if (tef != null) { 639 tef.dispose(); 640 } 641 Setup.getDefault().removePropertyChangeListener(this); 642 _tracksList.clear(); 643 fireTableDataChanged(); 644 } 645 646 // this table listens for changes to a location and it's tracks 647 @Override 648 public void propertyChange(PropertyChangeEvent e) { 649 if (Control.SHOW_PROPERTY) { 650 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), 651 e.getNewValue()); 652 } 653 if (e.getPropertyName().equals(Location.TRACK_LISTLENGTH_CHANGED_PROPERTY) || 654 e.getPropertyName().equals(Location.TRAIN_DIRECTION_CHANGED_PROPERTY)) { 655 updateList(); 656 fireTableDataChanged(); 657 } 658 if (e.getPropertyName().equals(Setup.SHOW_TRACK_MOVES_PROPERTY_CHANGE) || 659 e.getPropertyName().equals(Location.TRAIN_DIRECTION_CHANGED_PROPERTY) || 660 e.getPropertyName().equals(Setup.ROUTING_STAGING_PROPERTY_CHANGE)) { 661 setColumnsVisible(); 662 } 663 if (e.getSource().getClass().equals(Track.class) && 664 (e.getPropertyName().equals(Track.DROP_CHANGED_PROPERTY) || 665 e.getPropertyName().equals(Track.PICKUP_CHANGED_PROPERTY) || 666 e.getPropertyName().equals(Track.SCHEDULE_ID_CHANGED_PROPERTY) || 667 e.getPropertyName().equals(Track.LOADS_CHANGED_PROPERTY) || 668 e.getPropertyName().equals(Track.ROADS_CHANGED_PROPERTY) || 669 e.getPropertyName().equals(Track.DESTINATION_OPTIONS_CHANGED_PROPERTY) || 670 e.getPropertyName().equals(Track.POOL_CHANGED_PROPERTY) || 671 e.getPropertyName().equals(Track.PLANNED_PICKUPS_CHANGED_PROPERTY) || 672 e.getPropertyName().equals(Track.ALTERNATE_TRACK_CHANGED_PROPERTY) || 673 e.getPropertyName().equals(Track.SERVICE_ORDER_CHANGED_PROPERTY) || 674 e.getPropertyName().equals(Track.LOAD_OPTIONS_CHANGED_PROPERTY) || 675 e.getPropertyName().equals(Track.TRAIN_DIRECTION_CHANGED_PROPERTY) || 676 e.getPropertyName().equals(Track.TRACK_COMMENT_CHANGED_PROPERTY) || 677 e.getPropertyName().equals(Track.TRACK_REPORTER_CHANGED_PROPERTY))) { 678 setColumnsVisible(); 679 } 680 if (e.getSource() instanceof TableColumn && e.getPropertyName().equals("preferredWidth")) { 681 log.debug("Column width change"); 682 setDirty(true); 683 } 684 } 685 686 @Override 687 public void columnAdded(TableColumnModelEvent e) { 688 // do nothing 689 } 690 691 @Override 692 public void columnRemoved(TableColumnModelEvent e) { 693 // do nothing 694 } 695 696 @Override 697 public void columnMoved(TableColumnModelEvent e) { 698 if (e.getFromIndex() != e.getToIndex()) { 699 log.debug("Table Column Moved"); 700 setDirty(true); 701 } 702 } 703 704 @Override 705 public void columnMarginChanged(ChangeEvent e) { 706 // do nothing 707 } 708 709 @Override 710 public void columnSelectionChanged(ListSelectionEvent e) { 711 // do nothing 712 } 713 714 private final static Logger log = LoggerFactory.getLogger(TrackTableModel.class); 715}