001package jmri.jmrit.operations.trains.manualtrainbuilder.gui; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.util.ArrayList; 006import java.util.List; 007 008import javax.swing.*; 009import javax.swing.table.TableCellEditor; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014import jmri.InstanceManager; 015import jmri.jmrit.operations.OperationsTableModel; 016import jmri.jmrit.operations.locations.*; 017import jmri.jmrit.operations.rollingstock.cars.*; 018import jmri.jmrit.operations.routes.Route; 019import jmri.jmrit.operations.routes.RouteLocation; 020import jmri.jmrit.operations.setup.Control; 021import jmri.jmrit.operations.trains.Train; 022import jmri.jmrit.operations.trains.TrainManager; 023import jmri.jmrit.operations.trains.manualtrainbuilder.TrainManualBuild; 024import jmri.jmrit.operations.trains.manualtrainbuilder.TrainManualBuildItem; 025import jmri.jmrit.operations.trains.schedules.TrainSchedule; 026import jmri.jmrit.operations.trains.schedules.TrainScheduleManager; 027import jmri.util.swing.XTableColumnModel; 028import jmri.util.table.ButtonEditor; 029import jmri.util.table.ButtonRenderer; 030 031/** 032 * Table Model for edit of a schedule used by operations 033 * 034 * @author Daniel Boudreau Copyright (C) 2009, 2014 035 */ 036public class TrainManualBuildTableModel extends OperationsTableModel implements PropertyChangeListener { 037 038 // Defines the columns 039 private static final int ID_COLUMN = 0; 040 private static final int TYPE_COLUMN = ID_COLUMN + 1; 041 private static final int ROAD_COLUMN = TYPE_COLUMN + 1; 042 private static final int LOAD_COLUMN = ROAD_COLUMN + 1; 043 private static final int LOCATION_COLUMN = LOAD_COLUMN + 1; 044 private static final int LOC_TRACK_COLUMN = LOCATION_COLUMN + 1; 045 private static final int DESTINATION_COLUMN = LOC_TRACK_COLUMN + 1; 046 private static final int DEST_TRACK_COLUMN = DESTINATION_COLUMN + 1; 047 private static final int PICKUP_DAY_COLUMN = DEST_TRACK_COLUMN + 1; 048 private static final int COUNT_COLUMN = PICKUP_DAY_COLUMN + 1; 049 private static final int WARN_COLUMN = COUNT_COLUMN + 1; 050 private static final int FAIL_COLUMN = WARN_COLUMN + 1; 051 private static final int REMOVE_COLUMN = FAIL_COLUMN + 1; 052 private static final int UP_COLUMN = REMOVE_COLUMN + 1; 053 private static final int DOWN_COLUMN = UP_COLUMN + 1; 054 private static final int DELETE_COLUMN = DOWN_COLUMN + 1; 055 056 private static final int HIGHEST_COLUMN = DELETE_COLUMN + 1; 057 058 private static final String NONE = ""; 059 060 public TrainManualBuildTableModel() { 061 super(); 062 } 063 064 TrainManualBuild _manualBuild; 065 TrainManualBuildEditFrame _frame; 066 Train _train; 067 068 private void updateList() { 069 // first, remove listeners from the individual objects 070 removePropertyChangeManualBuildItems(); 071 _list = _manualBuild.getItemsBySequenceList(); 072 // and add them back in 073 for (TrainManualBuildItem mbi : _list) { 074 mbi.addPropertyChangeListener(this); 075 // covers the cases where destination or track is deleted 076 if (mbi.getDestination() != null) { 077 mbi.getDestination().addPropertyChangeListener(this); 078 } 079 if (mbi.getDestinationTrack() != null) { 080 mbi.getDestinationTrack().addPropertyChangeListener(this); 081 } 082 } 083 } 084 085 List<TrainManualBuildItem> _list = new ArrayList<>(); 086 087 protected void initTable(TrainManualBuildEditFrame frame, JTable table, TrainManualBuild tmb) { 088 super.initTable(table); 089 _manualBuild = tmb; 090 _frame = frame; 091 _train = InstanceManager.getDefault(TrainManager.class).getTrainById(_manualBuild.getTrainId()); 092 093 // add property listeners 094 _manualBuild.addPropertyChangeListener(this); 095 initTable(); 096 } 097 098 private void initTable() { 099 // Use XTableColumnModel so we can control which columns are visible 100 XTableColumnModel tcm = new XTableColumnModel(); 101 _table.setColumnModel(tcm); 102 _table.createDefaultColumnsFromModel(); 103 104 // Install the button handlers 105 ButtonRenderer buttonRenderer = new ButtonRenderer(); 106 TableCellEditor buttonEditor = new ButtonEditor(new javax.swing.JButton()); 107 tcm.getColumn(UP_COLUMN).setCellRenderer(buttonRenderer); 108 tcm.getColumn(UP_COLUMN).setCellEditor(buttonEditor); 109 tcm.getColumn(DOWN_COLUMN).setCellRenderer(buttonRenderer); 110 tcm.getColumn(DOWN_COLUMN).setCellEditor(buttonEditor); 111 tcm.getColumn(DELETE_COLUMN).setCellRenderer(buttonRenderer); 112 tcm.getColumn(DELETE_COLUMN).setCellEditor(buttonEditor); 113 114 // set column preferred widths 115 _table.getColumnModel().getColumn(ID_COLUMN).setPreferredWidth(35); 116 _table.getColumnModel().getColumn(TYPE_COLUMN).setPreferredWidth(90); 117 _table.getColumnModel().getColumn(ROAD_COLUMN).setPreferredWidth(90); 118 _table.getColumnModel().getColumn(LOAD_COLUMN).setPreferredWidth(90); 119 _table.getColumnModel().getColumn(LOCATION_COLUMN).setPreferredWidth(130); 120 _table.getColumnModel().getColumn(LOC_TRACK_COLUMN).setPreferredWidth(130); 121 _table.getColumnModel().getColumn(DESTINATION_COLUMN).setPreferredWidth(130); 122 _table.getColumnModel().getColumn(DEST_TRACK_COLUMN).setPreferredWidth(130); 123 _table.getColumnModel().getColumn(PICKUP_DAY_COLUMN).setPreferredWidth(90); 124 _table.getColumnModel().getColumn(COUNT_COLUMN).setPreferredWidth(45); 125 _table.getColumnModel().getColumn(WARN_COLUMN).setPreferredWidth(45); 126 _table.getColumnModel().getColumn(FAIL_COLUMN).setPreferredWidth(45); 127 _table.getColumnModel().getColumn(REMOVE_COLUMN).setPreferredWidth(60); 128 _table.getColumnModel().getColumn(UP_COLUMN).setPreferredWidth(60); 129 _table.getColumnModel().getColumn(DOWN_COLUMN).setPreferredWidth(70); 130 _table.getColumnModel().getColumn(DELETE_COLUMN).setPreferredWidth(70); 131 132 _frame.loadTableDetails(_table); 133 134 // does not use a table sorter 135 _table.setRowSorter(null); 136 137 updateList(); 138 } 139 140 @Override 141 public int getRowCount() { 142 return _list.size(); 143 } 144 145 @Override 146 public int getColumnCount() { 147 return HIGHEST_COLUMN; 148 } 149 150 @Override 151 public String getColumnName(int col) { 152 switch (col) { 153 case ID_COLUMN: 154 return Bundle.getMessage("Id"); 155 case TYPE_COLUMN: 156 return Bundle.getMessage("Type"); 157 case ROAD_COLUMN: 158 return Bundle.getMessage("Road"); 159 case LOAD_COLUMN: 160 return Bundle.getMessage("Load"); 161 case LOCATION_COLUMN: 162 return Bundle.getMessage("Location"); 163 case LOC_TRACK_COLUMN: 164 return Bundle.getMessage("Track"); 165 case DESTINATION_COLUMN: 166 return Bundle.getMessage("Destination"); 167 case DEST_TRACK_COLUMN: 168 return Bundle.getMessage("DestTrack"); 169 case PICKUP_DAY_COLUMN: 170 return Bundle.getMessage("Pickup"); 171 case COUNT_COLUMN: 172 return Bundle.getMessage("Count"); 173 case WARN_COLUMN: 174 return Bundle.getMessage("Warn"); 175 case FAIL_COLUMN: 176 return Bundle.getMessage("Fail"); 177 case REMOVE_COLUMN: 178 return Bundle.getMessage("Remove"); 179 case UP_COLUMN: 180 return Bundle.getMessage("Up"); 181 case DOWN_COLUMN: 182 return Bundle.getMessage("Down"); 183 case DELETE_COLUMN: 184 return Bundle.getMessage("ButtonDelete"); 185 default: 186 return "unknown"; // NOI18N 187 } 188 } 189 190 @Override 191 public Class<?> getColumnClass(int col) { 192 switch (col) { 193 case ID_COLUMN: 194 return String.class; 195 case TYPE_COLUMN: 196 case ROAD_COLUMN: 197 case LOAD_COLUMN: 198 case LOCATION_COLUMN: 199 case LOC_TRACK_COLUMN: 200 case DESTINATION_COLUMN: 201 case DEST_TRACK_COLUMN: 202 case PICKUP_DAY_COLUMN: 203 return JComboBox.class; 204 case COUNT_COLUMN: 205 return Integer.class; 206 case WARN_COLUMN: 207 case FAIL_COLUMN: 208 case REMOVE_COLUMN: 209 return Boolean.class; 210 case UP_COLUMN: 211 case DOWN_COLUMN: 212 case DELETE_COLUMN: 213 return JButton.class; 214 default: 215 return null; 216 } 217 } 218 219 @Override 220 public boolean isCellEditable(int row, int col) { 221 switch (col) { 222 case TYPE_COLUMN: 223 case ROAD_COLUMN: 224 case LOAD_COLUMN: 225 case LOCATION_COLUMN: 226 case LOC_TRACK_COLUMN: 227 case DESTINATION_COLUMN: 228 case DEST_TRACK_COLUMN: 229 case PICKUP_DAY_COLUMN: 230 case COUNT_COLUMN: 231 case WARN_COLUMN: 232 case FAIL_COLUMN: 233 case REMOVE_COLUMN: 234 case UP_COLUMN: 235 case DOWN_COLUMN: 236 case DELETE_COLUMN: 237 return true; 238 default: 239 return false; 240 } 241 } 242 243 @Override 244 public Object getValueAt(int row, int col) { 245 if (row >= getRowCount()) { 246 return "ERROR row " + row; // NOI18N 247 } 248 TrainManualBuildItem mbi = _list.get(row); 249 if (mbi == null) { 250 return "ERROR schedule item unknown " + row; // NOI18N 251 } 252 switch (col) { 253 case ID_COLUMN: 254 return mbi.getId(); 255 case TYPE_COLUMN: 256 return getTypeComboBox(mbi); 257 case ROAD_COLUMN: 258 return getRoadComboBox(mbi); 259 case LOAD_COLUMN: 260 return getLoadComboBox(mbi); 261 case LOCATION_COLUMN: 262 return getRouteLocationComboBox(mbi); 263 case LOC_TRACK_COLUMN: 264 return getLocationTrackComboBox(mbi); 265 case DESTINATION_COLUMN: 266 return getDestinationComboBox(mbi); 267 case DEST_TRACK_COLUMN: 268 return getDestTrackComboBox(mbi); 269 case PICKUP_DAY_COLUMN: 270 return getPickupDayComboBox(mbi); 271 case COUNT_COLUMN: 272 return mbi.getCount(); 273 case WARN_COLUMN: 274 return mbi.isWarnEnabled(); 275 case FAIL_COLUMN: 276 return mbi.isFailEnabled(); 277 case REMOVE_COLUMN: 278 return mbi.isRemoveEnabled(); 279 case UP_COLUMN: 280 return Bundle.getMessage("Up"); 281 case DOWN_COLUMN: 282 return Bundle.getMessage("Down"); 283 case DELETE_COLUMN: 284 return Bundle.getMessage("ButtonDelete"); 285 default: 286 return "unknown " + col; // NOI18N 287 } 288 } 289 290 @Override 291 public void setValueAt(Object value, int row, int col) { 292 if (value == null) { 293 log.debug("Warning schedule table row {} still in edit", row); 294 return; 295 } 296 TrainManualBuildItem mbi = _list.get(row); 297 switch (col) { 298 case TYPE_COLUMN: 299 setType(value, mbi); 300 break; 301 case ROAD_COLUMN: 302 setRoad(value, mbi); 303 break; 304 case LOAD_COLUMN: 305 setLoad(value, mbi); 306 break; 307 case LOCATION_COLUMN: 308 setRouteLocation(value, mbi); 309 break; 310 case LOC_TRACK_COLUMN: 311 setLocTrack(value, mbi); 312 break; 313 case DESTINATION_COLUMN: 314 setDestination(value, mbi); 315 break; 316 case DEST_TRACK_COLUMN: 317 setDestTrack(value, mbi); 318 break; 319 case PICKUP_DAY_COLUMN: 320 setPickupDay(value, mbi); 321 break; 322 case COUNT_COLUMN: 323 setCount(value, mbi); 324 break; 325 case WARN_COLUMN: 326 setWarn(value, mbi); 327 break; 328 case FAIL_COLUMN: 329 setFail(value, mbi); 330 break; 331 case REMOVE_COLUMN: 332 mbi.setRemoveEnabled(((Boolean) value).booleanValue()); 333 break; 334 case UP_COLUMN: 335 moveUpManualBuildItem(row); 336 break; 337 case DOWN_COLUMN: 338 moveDownManualBuildItem(row); 339 break; 340 case DELETE_COLUMN: 341 deleteManualBuildItem(row); 342 break; 343 default: 344 break; 345 } 346 } 347 348 private JComboBox<String> getTypeComboBox(TrainManualBuildItem mbi) { 349 JComboBox<String> cb = new JComboBox<>(); 350 cb.addItem(NONE); 351 for (String typeName : InstanceManager.getDefault(CarTypes.class).getNames()) { 352 if (_train.isTypeNameAccepted(typeName)) { 353 cb.addItem(typeName); 354 } 355 } 356 cb.setSelectedItem(mbi.getTypeName()); 357 // fix if type no longer accepted by train 358 if (!cb.getSelectedItem().equals(mbi.getTypeName())) { 359 mbi.setTypeName(NONE); 360 } 361 return cb; 362 } 363 364 private JComboBox<String> getRoadComboBox(TrainManualBuildItem mbi) { 365 JComboBox<String> cb = new JComboBox<>(); 366 cb.addItem(NONE); 367 for (String roadName : InstanceManager.getDefault(CarRoads.class).getNames(mbi.getTypeName())) { 368 if (_train.isCarRoadNameAccepted(roadName)) { 369 cb.addItem(roadName); 370 } 371 } 372 cb.setSelectedItem(mbi.getRoadName()); 373 // fix if road no longer accepted by train 374 if (!cb.getSelectedItem().equals(mbi.getRoadName())) { 375 mbi.setRoadName(NONE); 376 } 377 return cb; 378 } 379 380 protected JComboBox<String> getLoadComboBox(TrainManualBuildItem mbi) { 381 JComboBox<String> cb = InstanceManager.getDefault(CarLoads.class).getSelectComboBox(mbi.getTypeName()); 382 for (String loadName : InstanceManager.getDefault(CarLoads.class).getNames(mbi.getTypeName())) { 383 if (!_train.isLoadNameAccepted(loadName)) { 384 cb.removeItem(loadName); 385 } 386 } 387 cb.setSelectedItem(mbi.getLoadName()); 388 // fix if load no longer accepted by train 389 if (!cb.getSelectedItem().equals(mbi.getLoadName())) { 390 mbi.setLoadName(NONE); 391 } 392 return cb; 393 } 394 395 protected JComboBox<RouteLocation> getRouteLocationComboBox(TrainManualBuildItem mbi) { 396 JComboBox<RouteLocation> cb = new JComboBox<>(); 397 cb.addItem(null); 398 Route route = _train.getRoute(); 399 for (RouteLocation rl : route.getLocationsBySequenceList()) { 400 cb.addItem(rl); 401 } 402 filterRouteLocations(cb, mbi.getTypeName()); 403 cb.setSelectedItem(mbi.getRouteLocation()); 404 // fix if route location no longer exists 405 if (cb.getSelectedItem() != mbi.getRouteLocation()) { 406 mbi.setRouteLocation(null); 407 } 408 return cb; 409 } 410 411 protected JComboBox<Track> getLocationTrackComboBox(TrainManualBuildItem mbi) { 412 // log.debug("getTrackComboBox for ManualBuildItem "+si.getType()); 413 JComboBox<Track> cb = new JComboBox<>(); 414 if (mbi.getRouteLocation() != null) { 415 Location loc = mbi.getRouteLocation().getLocation(); 416 loc.updateComboBox(cb); 417 filterTracks(loc, cb, mbi.getTypeName(), mbi.getRoadName(), mbi.getLoadName()); 418 } 419 cb.setSelectedItem(mbi.getLocationTrack()); 420 // fix if track no longer exists 421 if (cb.getSelectedItem() != mbi.getLocationTrack()) { 422 mbi.setLocationTrack(null); 423 } 424 return cb; 425 } 426 427 protected JComboBox<Location> getDestinationComboBox(TrainManualBuildItem mbi) { 428 JComboBox<Location> cb = InstanceManager.getDefault(LocationManager.class).getComboBox(); 429 filterLocations(cb, mbi.getTypeName()); 430 cb.setSelectedItem(mbi.getDestination()); 431 // fix if destination no longer exists 432 if (cb.getSelectedItem() != mbi.getDestination()) { 433 mbi.setDestination(null); 434 } 435 return cb; 436 } 437 438 protected JComboBox<Track> getDestTrackComboBox(TrainManualBuildItem mbi) { 439 // log.debug("getTrackComboBox for ManualBuildItem "+si.getType()); 440 JComboBox<Track> cb = new JComboBox<>(); 441 if (mbi.getDestination() != null) { 442 Location dest = mbi.getDestination(); 443 dest.updateComboBox(cb); 444 filterTracks(dest, cb, mbi.getTypeName(), mbi.getRoadName(), mbi.getLoadName()); 445 } 446 cb.setSelectedItem(mbi.getDestinationTrack()); 447 // fix if track no longer exists 448 if (cb.getSelectedItem() != mbi.getDestinationTrack()) { 449 mbi.setDestinationTrack(null); 450 } 451 return cb; 452 } 453 454 private JComboBox<TrainSchedule> getPickupDayComboBox(TrainManualBuildItem mbi) { 455 JComboBox<TrainSchedule> cb = InstanceManager.getDefault(TrainScheduleManager.class).getSelectComboBox(); 456 TrainSchedule sch = 457 InstanceManager.getDefault(TrainScheduleManager.class).getScheduleById(mbi.getTrainScheduleId()); 458 cb.setSelectedItem(sch); 459 // fix if schedule no longer exists 460 if (cb.getSelectedItem() != sch) { 461 mbi.setTrainScheduleId(NONE); 462 } 463 return cb; 464 } 465 466 private void setType(Object value, TrainManualBuildItem mbi) { 467 String type = (String) ((JComboBox<?>) value).getSelectedItem(); 468 mbi.setTypeName(type); 469 } 470 471 private void setRoad(Object value, TrainManualBuildItem mbi) { 472 String road = (String) ((JComboBox<?>) value).getSelectedItem(); 473 mbi.setRoadName(road); 474 } 475 476 private void setLoad(Object value, TrainManualBuildItem mbi) { 477 String load = (String) ((JComboBox<?>) value).getSelectedItem(); 478 mbi.setLoadName(load); 479 } 480 481 private void setRouteLocation(Object value, TrainManualBuildItem mbi) { 482 mbi.setLocationTrack(null); 483 RouteLocation rl = (RouteLocation) ((JComboBox<?>) value).getSelectedItem(); 484 mbi.setRouteLocation(rl); 485 } 486 487 private void setLocTrack(Object value, TrainManualBuildItem mbi) { 488 Track track = (Track) ((JComboBox<?>) value).getSelectedItem(); 489 mbi.setLocationTrack(track); 490 } 491 492 private void setDestination(Object value, TrainManualBuildItem mbi) { 493 mbi.setDestinationTrack(null); 494 Location dest = (Location) ((JComboBox<?>) value).getSelectedItem(); 495 mbi.setDestination(dest); 496 } 497 498 private void setDestTrack(Object value, TrainManualBuildItem mbi) { 499 Track track = (Track) ((JComboBox<?>) value).getSelectedItem(); 500 mbi.setDestinationTrack(track); 501 } 502 503 private void setPickupDay(Object value, TrainManualBuildItem mbi) { 504 Object obj = ((JComboBox<?>) value).getSelectedItem(); 505 if (obj == null) { 506 mbi.setTrainScheduleId(TrainManualBuildItem.NONE); 507 } else if (obj.getClass().equals(TrainSchedule.class)) { 508 mbi.setTrainScheduleId(((TrainSchedule) obj).getId()); 509 } 510 } 511 512 private void setCount(Object value, TrainManualBuildItem mbi) { 513 mbi.setCount((int) value); 514 } 515 516 private void setWarn(Object value, TrainManualBuildItem mbi) { 517 mbi.setWarnEnabled(((Boolean) value).booleanValue()); 518 if (mbi.isWarnEnabled()) { 519 mbi.setFailEnabled(false); 520 } 521 } 522 523 private void setFail(Object value, TrainManualBuildItem mbi) { 524 mbi.setFailEnabled(((Boolean) value).booleanValue()); 525 if (mbi.isFailEnabled()) { 526 mbi.setWarnEnabled(false); 527 } 528 } 529 530 private void moveUpManualBuildItem(int row) { 531 log.debug("move schedule item up"); 532 _manualBuild.moveItemUp(_list.get(row)); 533 } 534 535 private void moveDownManualBuildItem(int row) { 536 log.debug("move schedule item down"); 537 _manualBuild.moveItemDown(_list.get(row)); 538 } 539 540 private void deleteManualBuildItem(int row) { 541 log.debug("Delete schedule item"); 542 _manualBuild.deleteItem(_list.get(row)); 543 } 544 545 // remove route locations that don't service the car's type 546 private void filterRouteLocations(JComboBox<RouteLocation> cb, String carType) { 547 for (int i = 1; i < cb.getItemCount(); i++) { 548 RouteLocation rl = cb.getItemAt(i); 549 if (!carType.equals(NONE) && !rl.getLocation().acceptsTypeName(carType)) { 550 cb.removeItem(rl); 551 i--; 552 } 553 } 554 } 555 556 // remove destinations that don't service the car's type 557 private void filterLocations(JComboBox<Location> cb, String carType) { 558 for (int i = 1; i < cb.getItemCount(); i++) { 559 Location loc = cb.getItemAt(i); 560 if (!carType.equals(NONE) && !loc.acceptsTypeName(carType)) { 561 cb.removeItem(loc); 562 i--; 563 } 564 } 565 } 566 567 // remove tracks that don't service the car's type, road, or load 568 private void filterTracks(Location loc, JComboBox<Track> cb, String carType, String carRoad, String carLoad) { 569 List<Track> tracks = loc.getTracksList(); 570 for (Track track : tracks) { 571 if (track.isStaging() || 572 (!carType.equals(NONE) && !track.isTypeNameAccepted(carType)) || 573 (!carRoad.equals(NONE) && !track.isRoadNameAccepted(carRoad)) || 574 (!carLoad.equals(NONE) && !track.isLoadNameAndCarTypeAccepted(carLoad, carType))) { 575 cb.removeItem(track); 576 } 577 } 578 } 579 580 @Override 581 public void propertyChange(PropertyChangeEvent e) { 582 if (Control.SHOW_PROPERTY) { 583 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 584 .getNewValue()); 585 } 586 if (e.getPropertyName().equals(TrainManualBuild.LISTCHANGE_CHANGED_PROPERTY)) { 587 updateList(); 588 fireTableDataChanged(); 589 } 590 if (e.getSource().getClass().equals(TrainManualBuildItem.class)) { 591 TrainManualBuildItem item = (TrainManualBuildItem) e.getSource(); 592 int row = _list.indexOf(item); 593 if (Control.SHOW_PROPERTY) { 594 log.debug("Update table row: {}", row); 595 } 596 if (row >= 0) { 597 fireTableRowsUpdated(row, row); 598 } 599 } 600 } 601 602 private void removePropertyChangeManualBuildItems() { 603 for (TrainManualBuildItem mbi : _list) { 604 mbi.removePropertyChangeListener(this); 605 if (mbi.getDestination() != null) { 606 mbi.getDestination().removePropertyChangeListener(this); 607 } 608 if (mbi.getDestinationTrack() != null) { 609 mbi.getDestinationTrack().removePropertyChangeListener(this); 610 } 611 } 612 } 613 614 public void dispose() { 615 if (_manualBuild != null) { 616 removePropertyChangeManualBuildItems(); 617 _manualBuild.removePropertyChangeListener(this); 618 } 619 } 620 621 private static final Logger log = LoggerFactory.getLogger(TrainManualBuildTableModel.class); 622}