001package jmri.jmrit.operations.rollingstock; 002 003import java.awt.GridBagLayout; 004import java.text.MessageFormat; 005import java.util.List; 006import java.util.ResourceBundle; 007 008import javax.swing.*; 009 010import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 011import jmri.InstanceManager; 012import jmri.jmrit.operations.OperationsFrame; 013import jmri.jmrit.operations.locations.*; 014import jmri.jmrit.operations.rollingstock.cars.Car; 015import jmri.jmrit.operations.rollingstock.cars.tools.CarsSetFrame; 016import jmri.jmrit.operations.rollingstock.engines.tools.EnginesSetFrame; 017import jmri.jmrit.operations.routes.Route; 018import jmri.jmrit.operations.routes.RouteLocation; 019import jmri.jmrit.operations.setup.Setup; 020import jmri.jmrit.operations.trains.Train; 021import jmri.jmrit.operations.trains.TrainManager; 022import jmri.util.swing.JmriJOptionPane; 023 024/** 025 * Frame for user to place RollingStock on the layout 026 * 027 * @author Dan Boudreau Copyright (C) 2010, 2011, 2012, 2013 028 * @param <T> the type of RollingStock supported by this frame 029 */ 030public abstract class RollingStockSetFrame<T extends RollingStock> extends OperationsFrame implements java.beans.PropertyChangeListener { 031 032 protected LocationManager locationManager = InstanceManager.getDefault(LocationManager.class); 033 protected TrainManager trainManager = InstanceManager.getDefault(TrainManager.class); 034 035 RollingStock _rs; 036 037 // labels 038 JLabel textRoad = new JLabel(); 039 JLabel textType = new JLabel(); 040 041 // major buttons 042 public JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 043 public JButton ignoreAllButton = new JButton(Bundle.getMessage("IgnoreAll")); 044 045 // combo boxes 046 public JComboBox<Location> locationBox = locationManager.getComboBox(); 047 public JComboBox<Track> trackLocationBox = new JComboBox<>(); 048 public JComboBox<Location> destinationBox = locationManager.getComboBox(); 049 public JComboBox<Track> trackDestinationBox = new JComboBox<>(); 050 public JComboBox<Location> finalDestinationBox = locationManager.getComboBox(); 051 public JComboBox<Track> finalDestTrackBox = new JComboBox<>(); 052 public JComboBox<Train> trainBox = trainManager.getTrainComboBox(); 053 054 // check boxes 055 public JCheckBox autoTrackCheckBox = new JCheckBox(Bundle.getMessage("Auto")); 056 public JCheckBox autoDestinationTrackCheckBox = new JCheckBox(Bundle.getMessage("Auto")); 057 public JCheckBox autoFinalDestTrackCheckBox = new JCheckBox(Bundle.getMessage("Auto")); 058 public JCheckBox autoTrainCheckBox = new JCheckBox(Bundle.getMessage("Auto")); 059 060 public JCheckBox locationUnknownCheckBox = new JCheckBox(Bundle.getMessage("LocationUnknown")); 061 public JCheckBox outOfServiceCheckBox = new JCheckBox(Bundle.getMessage("OutOfService")); 062 063 public JCheckBox ignoreStatusCheckBox = new JCheckBox(Bundle.getMessage("Ignore")); 064 public JCheckBox ignoreLocationCheckBox = new JCheckBox(Bundle.getMessage("Ignore")); 065 public JCheckBox ignoreDestinationCheckBox = new JCheckBox(Bundle.getMessage("Ignore")); 066 public JCheckBox ignoreFinalDestinationCheckBox = new JCheckBox(Bundle.getMessage("Ignore")); 067 public JCheckBox ignoreTrainCheckBox = new JCheckBox(Bundle.getMessage("Ignore")); 068 069 // optional panels 070 protected JPanel pOptional = new JPanel(); 071 protected JScrollPane paneOptional = new JScrollPane(pOptional); 072 protected JPanel pFinalDestination = new JPanel(); 073 074 // Auto checkbox states 075 private static boolean autoTrackCheckBoxSelected = false; 076 private static boolean autoDestinationTrackCheckBoxSelected = false; 077 private static boolean autoFinalDestTrackCheckBoxSelected = false; 078 private static boolean autoTrainCheckBoxSelected = false; 079 080 public RollingStockSetFrame(String title) { 081 super(title); 082 } 083 084 @Override 085 public void initComponents() { 086 // the following code sets the frame's initial state 087 // create panel 088 JPanel pPanel = new JPanel(); 089 pPanel.setLayout(new BoxLayout(pPanel, BoxLayout.Y_AXIS)); 090 091 // Layout the panel by rows 092 // row 1 093 JPanel pRow1 = new JPanel(); 094 pRow1.setLayout(new BoxLayout(pRow1, BoxLayout.X_AXIS)); 095 // row 1a 096 JPanel pRs = new JPanel(); 097 pRs.setLayout(new GridBagLayout()); 098 pRs.setBorder(BorderFactory.createTitledBorder(getRb().getString("rsType"))); 099 addItem(pRs, textRoad, 1, 0); 100 pRow1.add(pRs); 101 102 // row 1b 103 JPanel pType = new JPanel(); 104 pType.setLayout(new GridBagLayout()); 105 pType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type"))); 106 addItem(pType, textType, 1, 0); 107 pRow1.add(pType); 108 109 // row 1c 110 JPanel pStatus = new JPanel(); 111 pStatus.setLayout(new GridBagLayout()); 112 pStatus.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Status"))); 113 addItemLeft(pStatus, ignoreStatusCheckBox, 0, 0); 114 addItemLeft(pStatus, locationUnknownCheckBox, 1, 1); 115 addItemLeft(pStatus, outOfServiceCheckBox, 1, 0); 116 pRow1.add(pStatus); 117 118 pPanel.add(pRow1); 119 120 // row 2 121 JPanel pLocation = new JPanel(); 122 pLocation.setLayout(new GridBagLayout()); 123 pLocation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LocationAndTrack"))); 124 addItemLeft(pLocation, ignoreLocationCheckBox, 0, 1); 125 addItem(pLocation, locationBox, 1, 1); 126 trackLocationBox.setName("trackLocationBox"); 127 addItem(pLocation, trackLocationBox, 2, 1); 128 addItem(pLocation, autoTrackCheckBox, 3, 1); 129 pPanel.add(pLocation); 130 131 // optional panel 2 132 JPanel pOptional2 = new JPanel(); 133 JScrollPane paneOptional2 = new JScrollPane(pOptional2); 134 pOptional2.setLayout(new BoxLayout(pOptional2, BoxLayout.Y_AXIS)); 135 paneOptional2.setBorder(BorderFactory.createTitledBorder(Bundle 136 .getMessage("BorderLayoutOptionalProgram"))); 137 138 // row 6 139 JPanel pDestination = new JPanel(); 140 pDestination.setLayout(new GridBagLayout()); 141 pDestination.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("DestinationAndTrack"))); 142 addItemLeft(pDestination, ignoreDestinationCheckBox, 0, 1); 143 addItem(pDestination, destinationBox, 1, 1); 144 addItem(pDestination, trackDestinationBox, 2, 1); 145 addItem(pDestination, autoDestinationTrackCheckBox, 3, 1); 146 pOptional2.add(pDestination); 147 148 // row 7 149 pFinalDestination.setLayout(new GridBagLayout()); 150 pFinalDestination.setBorder(BorderFactory.createTitledBorder(Bundle 151 .getMessage("FinalDestinationAndTrack"))); 152 addItemLeft(pFinalDestination, ignoreFinalDestinationCheckBox, 0, 1); 153 addItem(pFinalDestination, finalDestinationBox, 1, 1); 154 addItem(pFinalDestination, finalDestTrackBox, 2, 1); 155 addItem(pFinalDestination, autoFinalDestTrackCheckBox, 3, 1); 156 pOptional2.add(pFinalDestination); 157 158 // row 8 159 JPanel pTrain = new JPanel(); 160 pTrain.setLayout(new GridBagLayout()); 161 pTrain.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Train"))); 162 addItemLeft(pTrain, ignoreTrainCheckBox, 0, 0); 163 addItem(pTrain, trainBox, 1, 0); 164 addItem(pTrain, autoTrainCheckBox, 2, 0); 165 pOptional2.add(pTrain); 166 167 // button panel 168 JPanel pButtons = new JPanel(); 169 pButtons.setLayout(new GridBagLayout()); 170 addItem(pButtons, ignoreAllButton, 1, 0); 171 addItem(pButtons, saveButton, 2, 0); 172 173 // add panels 174 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 175 getContentPane().add(pPanel); 176 getContentPane().add(paneOptional); 177 getContentPane().add(paneOptional2); 178 getContentPane().add(pButtons); 179 180 // Don't show ignore buttons 181 ignoreStatusCheckBox.setVisible(false); 182 ignoreLocationCheckBox.setVisible(false); 183 ignoreDestinationCheckBox.setVisible(false); 184 ignoreFinalDestinationCheckBox.setVisible(false); 185 ignoreTrainCheckBox.setVisible(false); 186 ignoreAllButton.setVisible(false); 187 188 // setup buttons 189 addButtonAction(ignoreAllButton); 190 addButtonAction(saveButton); 191 192 // setup combobox 193 addComboBoxAction(locationBox); 194 addComboBoxAction(destinationBox); 195 addComboBoxAction(finalDestinationBox); 196 addComboBoxAction(trainBox); 197 198 // setup checkbox 199 addCheckBoxAction(locationUnknownCheckBox); 200 addCheckBoxAction(outOfServiceCheckBox); 201 addCheckBoxAction(autoTrackCheckBox); 202 addCheckBoxAction(autoDestinationTrackCheckBox); 203 addCheckBoxAction(autoFinalDestTrackCheckBox); 204 addCheckBoxAction(autoTrainCheckBox); 205 206 addCheckBoxAction(ignoreStatusCheckBox); 207 addCheckBoxAction(ignoreLocationCheckBox); 208 addCheckBoxAction(ignoreDestinationCheckBox); 209 addCheckBoxAction(ignoreFinalDestinationCheckBox); 210 addCheckBoxAction(ignoreTrainCheckBox); 211 212 // set auto check box selected 213 autoTrackCheckBox.setSelected(autoTrackCheckBoxSelected); 214 autoDestinationTrackCheckBox.setSelected(autoDestinationTrackCheckBoxSelected); 215 autoFinalDestTrackCheckBox.setSelected(autoFinalDestTrackCheckBoxSelected); 216 autoTrainCheckBox.setSelected(autoTrainCheckBoxSelected); 217 218 // add tool tips 219 autoTrackCheckBox.setToolTipText(getRb().getString("rsTipAutoTrack")); 220 autoDestinationTrackCheckBox.setToolTipText(getRb().getString("rsTipAutoTrack")); 221 autoFinalDestTrackCheckBox.setToolTipText(getRb().getString("rsTipAutoTrack")); 222 autoTrainCheckBox.setToolTipText(Bundle.getMessage("rsTipAutoTrain")); 223 locationUnknownCheckBox.setToolTipText(Bundle.getMessage("TipLocationUnknown")); 224 225 ignoreStatusCheckBox.setToolTipText(Bundle.getMessage("TipIgnore")); 226 ignoreLocationCheckBox.setToolTipText(Bundle.getMessage("TipIgnore")); 227 ignoreDestinationCheckBox.setToolTipText(Bundle.getMessage("TipIgnore")); 228 ignoreFinalDestinationCheckBox.setToolTipText(Bundle.getMessage("TipIgnore")); 229 ignoreTrainCheckBox.setToolTipText(Bundle.getMessage("TipIgnore")); 230 231 // get notified if combo box gets modified 232 locationManager.addPropertyChangeListener(this); 233 // get notified if train combo box gets modified 234 trainManager.addPropertyChangeListener(this); 235 } 236 237 protected void load(RollingStock rs) { 238 _rs = rs; 239 textRoad.setText(_rs.getRoadName() + " " + _rs.getNumber()); 240 textType.setText(_rs.getTypeName()); 241 locationUnknownCheckBox.setSelected(_rs.isLocationUnknown()); 242 outOfServiceCheckBox.setSelected(_rs.isOutOfService()); 243 updateComboBoxes(); // load the location, destination, and final destination combo boxes 244 updateTrainComboBox(); // load the train combo box 245 enableComponents(!locationUnknownCheckBox.isSelected()); 246 // has the program generated a pick up and set out for this rolling stock? 247 if (_rs.getRouteLocation() != null || _rs.getRouteDestination() != null) { 248 if (_rs.getRouteLocation() != null) { 249 log.debug("rs ({}) has a pick up location ({})", _rs.toString(), _rs.getRouteLocation().getName()); 250 } 251 if (_rs.getRouteDestination() != null) { 252 log.debug("rs ({}) has a destination ({})", _rs.toString(), _rs.getRouteDestination().getName()); 253 } 254 if (getClass() == CarsSetFrame.class || getClass() == EnginesSetFrame.class) { 255 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsPressChangeWill"), getRb().getString( 256 "rsInRoute"), JmriJOptionPane.WARNING_MESSAGE); 257 } else { 258 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsPressSaveWill"), getRb().getString( 259 "rsInRoute"), JmriJOptionPane.WARNING_MESSAGE); 260 } 261 } 262 _rs.addPropertyChangeListener(this); 263 } 264 265 // Save button 266 @Override 267 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 268 if (ae.getSource() == saveButton) { 269 if (save() && Setup.isCloseWindowOnSaveEnabled()) { 270 dispose(); 271 } 272 } 273 } 274 275 abstract protected ResourceBundle getRb(); 276 277 protected boolean save() { 278 return change(_rs); 279 } 280 281 // change(RollingStock rs) will load the route location and the route destination if possible 282 RouteLocation rl; 283 RouteLocation rd; 284 285 @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "GUI ease of use") 286 protected boolean change(RollingStock rs) { 287 log.debug("Change button action for rs ({})", rs.toString()); 288 // save the auto buttons 289 autoTrackCheckBoxSelected = autoTrackCheckBox.isSelected(); 290 autoDestinationTrackCheckBoxSelected = autoDestinationTrackCheckBox.isSelected(); 291 autoFinalDestTrackCheckBoxSelected = autoFinalDestTrackCheckBox.isSelected(); 292 autoTrainCheckBoxSelected = autoTrainCheckBox.isSelected(); 293 294 // save the statuses 295 if (!ignoreStatusCheckBox.isSelected()) { 296 rs.setLocationUnknown(locationUnknownCheckBox.isSelected()); 297 rs.setOutOfService(outOfServiceCheckBox.isSelected()); 298 } 299 // update location 300 if (!changeLocation(rs)) { 301 return false; 302 } 303 // check to see if rolling stock is in staging and out of service (also location unknown) 304 if (outOfServiceCheckBox.isSelected() && rs.getTrack() != null && rs.getTrack().isStaging()) { 305 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsNeedToRemoveStaging"), getRb() 306 .getString("rsInStaging"), JmriJOptionPane.WARNING_MESSAGE); 307 // clear the rolling stock's location 308 rs.setLocation(null, null); 309 } 310 311 loadTrain(rs); 312 313 // update destination 314 if (!changeDestination(rs)) { 315 return false; 316 } 317 318 updateTrainComboBox(); 319 320 // check if train can service this rolling stock 321 if (!ignoreTrainCheckBox.isSelected()) { 322 Train train = rs.getTrain(); 323 if (train != null) { 324 // determine if train services this rs's type 325 if (!train.isTypeNameAccepted(rs.getTypeName())) { 326 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 327 "rsTrainNotServType"), new Object[]{rs.getTypeName(), train.getName()}), getRb() 328 .getString("rsNotMove"), 329 JmriJOptionPane.ERROR_MESSAGE); 330 // prevent rs from being picked up and delivered 331 setRouteLocationAndDestination(rs, train, null, null); 332 return false; 333 } 334 // determine if train services this rs's road 335 if (rs.getClass() == Car.class) { 336 Car car = (Car) rs; 337 if (!car.isCaboose() && !train.isCarRoadNameAccepted(car.getRoadName()) || 338 car.isCaboose() && !train.isCabooseRoadNameAccepted(car.getRoadName())) { 339 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 340 "rsTrainNotServRoad"), new Object[]{rs.getRoadName(), train.getName()}), getRb() 341 .getString("rsNotMove"), 342 JmriJOptionPane.ERROR_MESSAGE); 343 // prevent rs from being picked up and delivered 344 setRouteLocationAndDestination(rs, train, null, null); 345 return false; 346 } 347 } else if (!train.isLocoRoadNameAccepted(rs.getRoadName())) { 348 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 349 "rsTrainNotServRoad"), new Object[]{rs.getRoadName(), train.getName()}), getRb() 350 .getString("rsNotMove"), 351 JmriJOptionPane.ERROR_MESSAGE); 352 // prevent rs from being picked up and delivered 353 setRouteLocationAndDestination(rs, train, null, null); 354 return false; 355 } 356 // determine if train services this rs's built date 357 if (!train.isBuiltDateAccepted(rs.getBuilt())) { 358 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 359 "rsTrainNotServBuilt"), new Object[]{rs.getBuilt(), train.getName()}), getRb() 360 .getString("rsNotMove"), 361 JmriJOptionPane.ERROR_MESSAGE); 362 // prevent rs from being picked up and delivered 363 setRouteLocationAndDestination(rs, train, null, null); 364 return false; 365 } 366 // determine if train services this rs's owner 367 if (!train.isOwnerNameAccepted(rs.getOwnerName())) { 368 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 369 "rsTrainNotServOwner"), new Object[]{rs.getOwnerName(), train.getName()}), getRb() 370 .getString("rsNotMove"), 371 JmriJOptionPane.ERROR_MESSAGE); 372 // prevent rs from being picked up and delivered 373 setRouteLocationAndDestination(rs, train, null, null); 374 return false; 375 } 376 // determine if train services the location and destination selected by user 377 rl = null; 378 rd = null; 379 if (rs.getLocation() != null) { 380 Route route = train.getRoute(); 381 if (route != null) { 382 // this is a quick check, the actual rl and rd are set later in this routine. 383 rl = route.getLastLocationByName(rs.getLocationName()); 384 rd = route.getLastLocationByName(rs.getDestinationName()); 385 } 386 if (rl == null) { 387 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 388 "rsLocNotServ"), new Object[]{rs.getLocationName(), train.getName()}), 389 getRb().getString("rsNotMove"), JmriJOptionPane.ERROR_MESSAGE); 390 // prevent rs from being picked up and delivered 391 setRouteLocationAndDestination(rs, train, null, null); 392 return false; 393 } 394 if (rd == null && !rs.getDestinationName().equals(RollingStock.NONE)) { 395 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 396 "rsDestNotServ"), new Object[]{rs.getDestinationName(), train.getName()}), 397 getRb().getString("rsNotMove"), JmriJOptionPane.ERROR_MESSAGE); 398 // prevent rs from being picked up and delivered 399 setRouteLocationAndDestination(rs, train, null, null); 400 return false; 401 } 402 if (rd != null && route != null) { 403 // now determine if destination is after location 404 List<RouteLocation> routeSequence = route.getLocationsBySequenceList(); 405 boolean foundTrainLoc = false; // when true, found the train's location 406 boolean foundLoc = false; // when true, found the rs's location in the route 407 boolean foundDes = false; 408 for (RouteLocation rlocation : routeSequence) { 409 if (train.isTrainEnRoute() && !foundTrainLoc) { 410 if (train.getCurrentRouteLocation() != rlocation) { 411 continue; 412 } 413 foundTrainLoc = true; 414 } 415 if (rs.getLocationName().equals(rlocation.getName())) { 416 rl = rlocation; 417 foundLoc = true; 418 } 419 if (rs.getDestinationName().equals(rlocation.getName()) && foundLoc) { 420 rd = rlocation; 421 foundDes = true; 422 if (rs.getDestinationTrack() != null && 423 (rlocation.getTrainDirection() & 424 rs.getDestinationTrack().getTrainDirections()) == 0) { 425 continue; // destination track isn't serviced by the train's direction 426 } 427 break; 428 } 429 } 430 if (!foundLoc) { 431 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 432 "rsTrainEnRoute"), 433 new Object[]{rs.toString(), train.getName(), 434 rs.getLocationName()}), 435 getRb().getString("rsNotMove"), 436 JmriJOptionPane.ERROR_MESSAGE); 437 // prevent rs from being picked up and delivered 438 setRouteLocationAndDestination(rs, train, null, null); 439 return false; 440 } 441 if (!foundDes) { 442 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 443 "rsLocOrder"), 444 new Object[]{rs.getDestinationName(), 445 rs.getLocationName(), train.getName()}), 446 getRb().getString("rsNotMove"), 447 JmriJOptionPane.ERROR_MESSAGE); 448 // prevent rs from being picked up and delivered 449 setRouteLocationAndDestination(rs, train, null, null); 450 return false; 451 } 452 } 453 } 454 } 455 } 456 return true; 457 } 458 459 protected boolean changeLocation(RollingStock rs) { 460 if (!ignoreLocationCheckBox.isSelected()) { 461 if (locationBox.getSelectedItem() == null) { 462 rs.setLocation(null, null); 463 } else { 464 if (trackLocationBox.getSelectedItem() == null) { 465 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsFullySelect"), getRb() 466 .getString("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 467 return false; 468 } 469 // update location only if it has changed 470 if (rs.getLocation() == null || 471 !rs.getLocation().equals(locationBox.getSelectedItem()) || 472 rs.getTrack() == null || 473 !rs.getTrack().equals(trackLocationBox.getSelectedItem())) { 474 String status = rs.setLocation((Location) locationBox.getSelectedItem(), 475 (Track) trackLocationBox.getSelectedItem()); 476 rs.setLastRouteId(RollingStock.NONE); // clear last route id 477 if (!status.equals(Track.OKAY)) { 478 log.debug("Can't set rs's location because of {}", status); 479 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 480 "rsCanNotLocMsg"), new Object[]{rs.toString(), status}), getRb() 481 .getString("rsCanNotLoc"), 482 JmriJOptionPane.ERROR_MESSAGE); 483 // does the user want to force the rolling stock to this track? 484 int results = JmriJOptionPane.showOptionDialog(this, MessageFormat.format(getRb() 485 .getString("rsForce"), 486 new Object[]{rs.toString(), 487 (Track) trackLocationBox.getSelectedItem()}), 488 MessageFormat.format(getRb() 489 .getString("rsOverride"), new Object[]{status}), 490 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, null, null); 491 if (results == JmriJOptionPane.YES_OPTION) { 492 log.debug("Force rolling stock to track"); 493 rs.setLocation((Location) locationBox.getSelectedItem(), (Track) trackLocationBox 494 .getSelectedItem(), RollingStock.FORCE); 495 } else { 496 return false; 497 } 498 } 499 } 500 } 501 } 502 return true; 503 } 504 505 private void loadTrain(RollingStock rs) { 506 if (!ignoreTrainCheckBox.isSelected()) { 507 if (trainBox.getSelectedItem() == null) { 508 if (rs.getTrain() != null) { 509 // prevent rs from being picked up and delivered 510 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 511 } 512 rs.setTrain(null); 513 } else { 514 Train train = (Train) trainBox.getSelectedItem(); 515 if (rs.getTrain() != null && !rs.getTrain().equals(train)) { 516 // prevent rs from being picked up and delivered 517 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 518 } 519 rs.setTrain(train); 520 } 521 } 522 } 523 524 private boolean changeDestination(RollingStock rs) { 525 if (!ignoreDestinationCheckBox.isSelected()) { 526 if (destinationBox.getSelectedItem() == null) { 527 rs.setDestination(null, null); 528 } else { 529 Track destTrack = null; 530 if (trackDestinationBox.getSelectedItem() != null) { 531 destTrack = (Track) trackDestinationBox.getSelectedItem(); 532 } 533 log.debug("changeDestination: {}, ({})", destinationBox.getSelectedItem(), 534 destTrack); 535 if (destTrack != null && 536 rs.getDestinationTrack() != destTrack && 537 destTrack.isStaging() && 538 (rs.getTrain() == null || !rs.getTrain().isBuilt())) { 539 log.debug("Destination track ({}) is staging", destTrack.getName()); 540 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsDoNotSelectStaging"), getRb() 541 .getString("rsCanNotDest"), JmriJOptionPane.ERROR_MESSAGE); 542 return false; 543 } 544 // determine is user changed the destination track and is part of train 545 if (destTrack != null && 546 rs.getDestinationTrack() != destTrack && 547 rs.getTrain() != null && 548 rs.getTrain().isBuilt() && 549 rs.getRouteLocation() != null) { 550 log.debug("Rolling stock ({}) has new track destination in built train ({})", 551 rs.toString(), rs.getTrainName()); 552 rs.getTrain().setModified(true); 553 } 554 String status = rs.setDestination((Location) destinationBox.getSelectedItem(), destTrack); 555 if (!status.equals(Track.OKAY)) { 556 log.debug("Can't set rs's destination because of {}", status); 557 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 558 "rsCanNotDestMsg"), new Object[]{rs.toString(), status}), getRb().getString( 559 "rsCanNotDest"), 560 JmriJOptionPane.ERROR_MESSAGE); 561 return false; 562 } 563 } 564 } 565 return true; 566 } 567 568 /* 569 * Checks to see if rolling stock's location or destination has changed, and 570 * if so, removes the rolling stock from the train. Also allows user to add 571 * or remove rolling stock to or from train. 572 */ 573 protected void checkTrain(RollingStock rs) { 574 Train train = rs.getTrain(); 575 if (train != null && train.isBuilt()) { 576 if (rs.getRouteLocation() != null && 577 rs.getRouteDestination() != null && 578 rs.getTrack() == null) { 579 // no track 580 setRouteLocationAndDestination(rs, train, null, null); 581 } 582 if (rs.getRouteLocation() != null && 583 rs.getRouteDestination() != null && 584 rl != null && 585 rd != null && 586 (!rs.getRouteLocation().getName().equals(rl.getName()) || 587 !rs.getRouteDestination().getName().equals(rd.getName()))) { 588 // user changed rolling stock location or destination 589 setRouteLocationAndDestination(rs, train, null, null); 590 } 591 if (rs.getRouteLocation() != null || rs.getRouteDestination() != null) { 592 if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(getRb().getString( 593 "rsRemoveRsFromTrain"), new Object[]{rs.toString(), train.getName()}), getRb() 594 .getString("rsInRoute"), 595 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 596 // prevent rs from being picked up and delivered 597 setRouteLocationAndDestination(rs, train, null, null); 598 } 599 } else if (rl != null && rd != null && rs.getDestinationTrack() != null) { 600 if (rs.getDestinationTrack().getLocation().isStaging() && 601 !rs.getDestinationTrack().equals(train.getTerminationTrack())) { 602 log.debug("Rolling stock destination track is staging and not the same as train"); 603 JmriJOptionPane.showMessageDialog(this, 604 Bundle.getMessage("rsMustSelectSameTrack", train.getTerminationTrack() 605 .getName()), 606 Bundle.getMessage("rsStagingTrackError"), JmriJOptionPane.ERROR_MESSAGE); 607 } else if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format( 608 getRb().getString("rsAddRsToTrain"), new Object[]{rs.toString(), train.getName()}), 609 getRb().getString("rsAddManuallyToTrain"), 610 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 611 // set new pick up and set out locations 612 setRouteLocationAndDestination(rs, train, rl, rd); 613 log.debug("Add rolling stock ({}) to train ({}) route pick up {} drop {}", rs.toString(), train 614 .getName(), rl.getId(), rd.getId()); // NOI18N 615 } 616 } 617 } 618 } 619 620 protected void setRouteLocationAndDestination(RollingStock rs, Train train, RouteLocation rl, 621 RouteLocation rd) { 622 if (rs.getRouteLocation() != null || rl != null) { 623 train.setModified(true); 624 } 625 // check destination track is staging 626 if (rl == null && 627 rd == null && 628 rs.getDestinationTrack() != null && 629 rs.getDestinationTrack().getLocation().isStaging()) { 630 log.debug("Rolling stock destination track is staging"); 631 rs.setDestination(null, null); 632 } 633 rs.setRouteLocation(rl); 634 rs.setRouteDestination(rd); 635 } 636 637 protected void updateComboBoxes() { 638 log.debug("update combo boxes"); 639 locationManager.updateComboBox(locationBox); 640 locationManager.updateComboBox(destinationBox); 641 locationManager.updateComboBox(finalDestinationBox); 642 643 updateLocationComboBoxes(); 644 updateDestinationComboBoxes(); 645 } 646 647 protected boolean updateGroup(List<T> list) { 648 for (RollingStock rs : list) { 649 if (rs == _rs) { 650 continue; 651 } 652 // Location status and out of service 653 if (!ignoreStatusCheckBox.isSelected()) { 654 rs.setLocationUnknown(locationUnknownCheckBox.isSelected()); 655 rs.setOutOfService(outOfServiceCheckBox.isSelected()); 656 } 657 // update location and destination 658 if (!changeLocation(rs)) { 659 return false; 660 } 661 if (!changeDestination(rs)) { 662 return false; 663 } 664 665 if (!ignoreTrainCheckBox.isSelected()) { 666 if (trainBox.getSelectedItem() == null) { 667 rs.setTrain(null); 668 } else { 669 rs.setTrain((Train) trainBox.getSelectedItem()); 670 } 671 } 672 // set the route location and destination to match 673 rs.setRouteLocation(_rs.getRouteLocation()); 674 rs.setRouteDestination(_rs.getRouteDestination()); 675 } 676 return true; 677 } 678 679 @Override 680 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 681 log.debug("checkbox action "); 682 if (ae.getSource() == locationUnknownCheckBox) { 683 outOfServiceCheckBox.setSelected(locationUnknownCheckBox.isSelected()); 684 enableComponents(!locationUnknownCheckBox.isSelected()); 685 } 686 if (ae.getSource() == autoTrackCheckBox) { 687 updateLocationTrackComboBox(); 688 } 689 if (ae.getSource() == autoDestinationTrackCheckBox) { 690 updateDestinationTrackComboBox(); 691 } 692 if (ae.getSource() == ignoreStatusCheckBox) { 693 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 694 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 695 } 696 if (ae.getSource() == ignoreLocationCheckBox) { 697 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 698 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 699 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 700 } 701 if (ae.getSource() == ignoreDestinationCheckBox) { 702 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 703 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 704 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 705 } 706 if (ae.getSource() == ignoreFinalDestinationCheckBox) { 707 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 708 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 709 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 710 } 711 if (ae.getSource() == ignoreTrainCheckBox) { 712 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 713 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 714 } 715 } 716 717 protected void enableComponents(boolean enabled) { 718 // combo boxes 719 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 720 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 721 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 722 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 723 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 724 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 725 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 726 // checkboxes 727 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 728 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 729 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 730 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 731 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 732 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected() & enabled); 733 734 ignoreStatusCheckBox.setEnabled(enabled); 735 ignoreLocationCheckBox.setEnabled(enabled); 736 ignoreDestinationCheckBox.setEnabled(enabled); 737 ignoreFinalDestinationCheckBox.setEnabled(Setup.isCarRoutingEnabled() & enabled); 738 ignoreTrainCheckBox.setEnabled(enabled); 739 } 740 741 // location combo box 742 @Override 743 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 744 if (ae.getSource() == locationBox) { 745 updateLocationTrackComboBox(); 746 } 747 if (ae.getSource() == destinationBox || ae.getSource() == trainBox) { 748 updateDestinationTrackComboBox(); 749 } 750 } 751 752 protected void updateLocationComboBoxes() { 753 log.debug("update location combo boxes"); 754 if (_rs != null) { 755 locationBox.setSelectedItem(_rs.getLocation()); 756 } 757 // now update track combo boxes 758 updateLocationTrackComboBox(); 759 } 760 761 protected void updateLocationTrackComboBox() { 762 log.debug("update location track combobox"); 763 if (locationBox.getSelectedItem() == null) { 764 trackLocationBox.removeAllItems(); 765 } else { 766 log.debug("RollingStockFrame sees location: {}", locationBox.getSelectedItem()); 767 Location l = (Location) locationBox.getSelectedItem(); 768 l.updateComboBox(trackLocationBox, _rs, autoTrackCheckBox.isSelected(), false); 769 if (_rs != null && _rs.getLocation() != null && _rs.getLocation().equals(l) && _rs.getTrack() != null) { 770 trackLocationBox.setSelectedItem(_rs.getTrack()); 771 } 772 } 773 } 774 775 protected void updateDestinationComboBoxes() { 776 log.debug("update destination combo boxes"); 777 if (_rs != null) { 778 destinationBox.setSelectedItem(_rs.getDestination()); 779 } 780 // now update track combo boxes 781 updateDestinationTrackComboBox(); 782 } 783 784 protected void updateDestinationTrackComboBox() { 785 log.debug("update destination track combobox"); 786 if (destinationBox.getSelectedItem() == null) { 787 trackDestinationBox.removeAllItems(); 788 } else { 789 log.debug("updateDestinationTrackComboBox destination: {}, ({})", destinationBox.getSelectedItem(), 790 trackDestinationBox.getSelectedItem()); 791 Location destination = (Location) destinationBox.getSelectedItem(); 792 Track track = null; 793 if (trackDestinationBox.getSelectedItem() != null) { 794 track = (Track) trackDestinationBox.getSelectedItem(); 795 } 796 destination.updateComboBox(trackDestinationBox, _rs, autoDestinationTrackCheckBox.isSelected(), true); 797 // check for staging, add track if train is built and terminates into staging 798 if (autoDestinationTrackCheckBox.isSelected() && trainBox.getSelectedItem() != null) { 799 Train train = (Train) trainBox.getSelectedItem(); 800 if (train.isBuilt() && 801 train.getTerminationTrack() != null && 802 train.getTerminationTrack().getLocation() == destination) { 803 trackDestinationBox.addItem(train.getTerminationTrack()); 804 trackDestinationBox.setSelectedItem(track); 805 } 806 } 807 if (_rs != null && 808 _rs.getDestination() != null && 809 _rs.getDestination().equals(destination) && 810 _rs.getDestinationTrack() != null) { 811 trackDestinationBox.setSelectedItem(_rs.getDestinationTrack()); 812 } else if (track != null) { 813 trackDestinationBox.setSelectedItem(track); 814 } 815 } 816 } 817 818 protected void updateTrainComboBox() { 819 log.debug("update train combo box"); 820 trainManager.updateTrainComboBox(trainBox); 821 if (_rs != null) { 822 trainBox.setSelectedItem(_rs.getTrain()); 823 } 824 } 825 826 @Override 827 public void dispose() { 828 if (_rs != null) { 829 _rs.removePropertyChangeListener(this); 830 } 831 locationManager.removePropertyChangeListener(this); 832 trainManager.removePropertyChangeListener(this); 833 super.dispose(); 834 } 835 836 @Override 837 public void propertyChange(java.beans.PropertyChangeEvent e) { 838 log.debug("PropertyChange ({}) new: ({})", e.getPropertyName(), e.getNewValue()); 839 if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY)) { 840 updateComboBoxes(); 841 } 842 if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY)) { 843 updateTrainComboBox(); 844 } 845 if (e.getPropertyName().equals(RollingStock.TRACK_CHANGED_PROPERTY)) { 846 updateLocationComboBoxes(); 847 } 848 if (e.getPropertyName().equals(RollingStock.DESTINATION_TRACK_CHANGED_PROPERTY)) { 849 updateDestinationComboBoxes(); 850 } 851 if (e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY)) { 852 if (_rs != null) { 853 trainBox.setSelectedItem(_rs.getTrain()); 854 } 855 } 856 } 857 858 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RollingStockSetFrame.class); 859}