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