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.getTrain() != null && 248 _rs.getTrain().isBuilt() && 249 (_rs.getRouteLocation() != null || _rs.getRouteDestination() != null)) { 250 if (_rs.getRouteLocation() != null) { 251 log.debug("rs ({}) has a pick up location ({})", _rs.toString(), _rs.getRouteLocation().getName()); 252 } 253 if (_rs.getRouteDestination() != null) { 254 log.debug("rs ({}) has a destination ({})", _rs.toString(), _rs.getRouteDestination().getName()); 255 } 256 if (getClass() == CarsSetFrame.class || getClass() == EnginesSetFrame.class) { 257 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsPressChangeWill"), getRb().getString( 258 "rsInRoute"), JmriJOptionPane.WARNING_MESSAGE); 259 } else { 260 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsPressSaveWill"), getRb().getString( 261 "rsInRoute"), JmriJOptionPane.WARNING_MESSAGE); 262 } 263 } 264 _rs.addPropertyChangeListener(this); 265 } 266 267 // Save button 268 @Override 269 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 270 if (ae.getSource() == saveButton) { 271 if (save() && Setup.isCloseWindowOnSaveEnabled()) { 272 dispose(); 273 } 274 } 275 } 276 277 abstract protected ResourceBundle getRb(); 278 279 protected boolean save() { 280 return change(_rs); 281 } 282 283 // change(RollingStock rs) will load the route location and the route destination if possible 284 RouteLocation rl; 285 RouteLocation rd; 286 287 @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "GUI ease of use") 288 protected boolean change(RollingStock rs) { 289 log.debug("Change button action for rs ({})", rs.toString()); 290 // save the auto buttons 291 autoTrackCheckBoxSelected = autoTrackCheckBox.isSelected(); 292 autoDestinationTrackCheckBoxSelected = autoDestinationTrackCheckBox.isSelected(); 293 autoFinalDestTrackCheckBoxSelected = autoFinalDestTrackCheckBox.isSelected(); 294 autoTrainCheckBoxSelected = autoTrainCheckBox.isSelected(); 295 296 // save the statuses 297 if (!ignoreStatusCheckBox.isSelected()) { 298 rs.setLocationUnknown(locationUnknownCheckBox.isSelected()); 299 rs.setOutOfService(outOfServiceCheckBox.isSelected()); 300 } 301 // update location 302 if (!changeLocation(rs)) { 303 return false; 304 } 305 // check to see if rolling stock is in staging and out of service (also location unknown) 306 if (outOfServiceCheckBox.isSelected() && rs.getTrack() != null && rs.getTrack().isStaging()) { 307 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsNeedToRemoveStaging"), getRb() 308 .getString("rsInStaging"), JmriJOptionPane.WARNING_MESSAGE); 309 // clear the rolling stock's location 310 rs.setLocation(null, null); 311 } 312 313 loadTrain(rs); 314 315 // update destination 316 if (!changeDestination(rs)) { 317 return false; 318 } 319 320 updateTrainComboBox(); 321 322 // check if train can service this rolling stock 323 if (!ignoreTrainCheckBox.isSelected()) { 324 Train train = rs.getTrain(); 325 if (train != null) { 326 // determine if train services this rs's type 327 if (!train.isTypeNameAccepted(rs.getTypeName())) { 328 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 329 "rsTrainNotServType"), new Object[]{rs.getTypeName(), train.getName()}), getRb() 330 .getString("rsNotMove"), 331 JmriJOptionPane.ERROR_MESSAGE); 332 // prevent rs from being picked up and delivered 333 setRouteLocationAndDestination(rs, train, null, null); 334 return false; 335 } 336 // determine if train services this rs's road 337 if (rs.getClass() == Car.class) { 338 Car car = (Car) rs; 339 if (!car.isCaboose() && !train.isCarRoadNameAccepted(car.getRoadName()) || 340 car.isCaboose() && !train.isCabooseRoadNameAccepted(car.getRoadName())) { 341 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 342 "rsTrainNotServRoad"), new Object[]{rs.getRoadName(), train.getName()}), getRb() 343 .getString("rsNotMove"), 344 JmriJOptionPane.ERROR_MESSAGE); 345 // prevent rs from being picked up and delivered 346 setRouteLocationAndDestination(rs, train, null, null); 347 return false; 348 } 349 } else if (!train.isLocoRoadNameAccepted(rs.getRoadName())) { 350 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 351 "rsTrainNotServRoad"), new Object[]{rs.getRoadName(), train.getName()}), getRb() 352 .getString("rsNotMove"), 353 JmriJOptionPane.ERROR_MESSAGE); 354 // prevent rs from being picked up and delivered 355 setRouteLocationAndDestination(rs, train, null, null); 356 return false; 357 } 358 // determine if train services this rs's built date 359 if (!train.isBuiltDateAccepted(rs.getBuilt())) { 360 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 361 "rsTrainNotServBuilt"), new Object[]{rs.getBuilt(), train.getName()}), getRb() 362 .getString("rsNotMove"), 363 JmriJOptionPane.ERROR_MESSAGE); 364 // prevent rs from being picked up and delivered 365 setRouteLocationAndDestination(rs, train, null, null); 366 return false; 367 } 368 // determine if train services this rs's owner 369 if (!train.isOwnerNameAccepted(rs.getOwnerName())) { 370 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 371 "rsTrainNotServOwner"), new Object[]{rs.getOwnerName(), train.getName()}), getRb() 372 .getString("rsNotMove"), 373 JmriJOptionPane.ERROR_MESSAGE); 374 // prevent rs from being picked up and delivered 375 setRouteLocationAndDestination(rs, train, null, null); 376 return false; 377 } 378 // determine if train services the location and destination selected by user 379 rl = null; 380 rd = null; 381 if (rs.getLocation() != null) { 382 Route route = train.getRoute(); 383 if (route != null) { 384 // this is a quick check, the actual rl and rd are set later in this routine. 385 rl = route.getLastLocationByName(rs.getLocationName()); 386 rd = route.getLastLocationByName(rs.getDestinationName()); 387 } 388 if (rl == null) { 389 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 390 "rsLocNotServ"), new Object[]{rs.getLocationName(), train.getName()}), 391 getRb().getString("rsNotMove"), JmriJOptionPane.ERROR_MESSAGE); 392 // prevent rs from being picked up and delivered 393 setRouteLocationAndDestination(rs, train, null, null); 394 return false; 395 } 396 if (rd == null && !rs.getDestinationName().equals(RollingStock.NONE)) { 397 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 398 "rsDestNotServ"), new Object[]{rs.getDestinationName(), train.getName()}), 399 getRb().getString("rsNotMove"), JmriJOptionPane.ERROR_MESSAGE); 400 // prevent rs from being picked up and delivered 401 setRouteLocationAndDestination(rs, train, null, null); 402 return false; 403 } 404 if (rd != null && route != null) { 405 // now determine if destination is after location 406 List<RouteLocation> routeSequence = route.getLocationsBySequenceList(); 407 boolean foundTrainLoc = false; // when true, found the train's location 408 boolean foundLoc = false; // when true, found the rs's location in the route 409 boolean foundDes = false; 410 for (RouteLocation rlocation : routeSequence) { 411 if (train.isTrainEnRoute() && !foundTrainLoc) { 412 if (train.getCurrentRouteLocation() != rlocation) { 413 continue; 414 } 415 foundTrainLoc = true; 416 } 417 if (rs.getLocationName().equals(rlocation.getName())) { 418 rl = rlocation; 419 foundLoc = true; 420 } 421 if (rs.getDestinationName().equals(rlocation.getName()) && foundLoc) { 422 rd = rlocation; 423 foundDes = true; 424 if (rs.getDestinationTrack() != null && 425 (rlocation.getTrainDirection() & 426 rs.getDestinationTrack().getTrainDirections()) == 0) { 427 continue; // destination track isn't serviced by the train's direction 428 } 429 break; 430 } 431 } 432 if (!foundLoc) { 433 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 434 "rsTrainEnRoute"), 435 new Object[]{rs.toString(), train.getName(), 436 rs.getLocationName()}), 437 getRb().getString("rsNotMove"), 438 JmriJOptionPane.ERROR_MESSAGE); 439 // prevent rs from being picked up and delivered 440 setRouteLocationAndDestination(rs, train, null, null); 441 return false; 442 } 443 if (!foundDes) { 444 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 445 "rsLocOrder"), 446 new Object[]{rs.getDestinationName(), 447 rs.getLocationName(), train.getName()}), 448 getRb().getString("rsNotMove"), 449 JmriJOptionPane.ERROR_MESSAGE); 450 // prevent rs from being picked up and delivered 451 setRouteLocationAndDestination(rs, train, null, null); 452 return false; 453 } 454 } 455 } 456 } 457 } 458 return true; 459 } 460 461 protected boolean changeLocation(RollingStock rs) { 462 if (!ignoreLocationCheckBox.isSelected()) { 463 if (locationBox.getSelectedItem() == null) { 464 rs.setLocation(null, null); 465 } else { 466 if (trackLocationBox.getSelectedItem() == null) { 467 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsFullySelect"), getRb() 468 .getString("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 469 return false; 470 } 471 // update location only if it has changed 472 if (rs.getLocation() == null || 473 !rs.getLocation().equals(locationBox.getSelectedItem()) || 474 rs.getTrack() == null || 475 !rs.getTrack().equals(trackLocationBox.getSelectedItem())) { 476 String status = rs.setLocation((Location) locationBox.getSelectedItem(), 477 (Track) trackLocationBox.getSelectedItem()); 478 rs.setLastRouteId(RollingStock.NONE); // clear last route id 479 rs.setLastTrain(null); // clear last train 480 if (!status.equals(Track.OKAY)) { 481 log.debug("Can't set rs's location because of {}", status); 482 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 483 "rsCanNotLocMsg"), new Object[]{rs.toString(), status}), getRb() 484 .getString("rsCanNotLoc"), 485 JmriJOptionPane.ERROR_MESSAGE); 486 // does the user want to force the rolling stock to this track? 487 int results = JmriJOptionPane.showOptionDialog(this, MessageFormat.format(getRb() 488 .getString("rsForce"), 489 new Object[]{rs.toString(), 490 (Track) trackLocationBox.getSelectedItem()}), 491 MessageFormat.format(getRb() 492 .getString("rsOverride"), new Object[]{status}), 493 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, null, null); 494 if (results == JmriJOptionPane.YES_OPTION) { 495 log.debug("Force rolling stock to track"); 496 rs.setLocation((Location) locationBox.getSelectedItem(), (Track) trackLocationBox 497 .getSelectedItem(), RollingStock.FORCE); 498 } else { 499 return false; 500 } 501 } 502 } 503 } 504 } 505 return true; 506 } 507 508 private void loadTrain(RollingStock rs) { 509 if (!ignoreTrainCheckBox.isSelected()) { 510 if (trainBox.getSelectedItem() == null) { 511 if (rs.getTrain() != null) { 512 // prevent rs from being picked up and delivered 513 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 514 } 515 rs.setTrain(null); 516 } else { 517 Train train = (Train) trainBox.getSelectedItem(); 518 if (rs.getTrain() != null && !rs.getTrain().equals(train)) { 519 // prevent rs from being picked up and delivered 520 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 521 } 522 rs.setTrain(train); 523 } 524 } 525 } 526 527 private boolean changeDestination(RollingStock rs) { 528 if (!ignoreDestinationCheckBox.isSelected()) { 529 if (destinationBox.getSelectedItem() == null) { 530 rs.setDestination(null, null); 531 } else { 532 Track destTrack = null; 533 if (trackDestinationBox.getSelectedItem() != null) { 534 destTrack = (Track) trackDestinationBox.getSelectedItem(); 535 } 536 log.debug("changeDestination: {}, ({})", destinationBox.getSelectedItem(), 537 destTrack); 538 if (destTrack != null && 539 rs.getDestinationTrack() != destTrack && 540 destTrack.isStaging() && 541 (rs.getTrain() == null || !rs.getTrain().isBuilt())) { 542 log.debug("Destination track ({}) is staging", destTrack.getName()); 543 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsDoNotSelectStaging"), getRb() 544 .getString("rsCanNotDest"), JmriJOptionPane.ERROR_MESSAGE); 545 return false; 546 } 547 // determine is user changed the destination track and is part of train 548 if (destTrack != null && 549 rs.getDestinationTrack() != destTrack && 550 rs.getTrain() != null && 551 rs.getTrain().isBuilt() && 552 rs.getRouteLocation() != null) { 553 log.debug("Rolling stock ({}) has new track destination in built train ({})", 554 rs.toString(), rs.getTrainName()); 555 rs.getTrain().setModified(true); 556 } 557 String status = rs.setDestination((Location) destinationBox.getSelectedItem(), destTrack); 558 if (!status.equals(Track.OKAY)) { 559 log.debug("Can't set rs's destination because of {}", status); 560 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 561 "rsCanNotDestMsg"), new Object[]{rs.toString(), status}), getRb().getString( 562 "rsCanNotDest"), 563 JmriJOptionPane.ERROR_MESSAGE); 564 return false; 565 } 566 } 567 } 568 return true; 569 } 570 571 /* 572 * Checks to see if rolling stock's location or destination has changed, and 573 * if so, removes the rolling stock from the train. Also allows user to add 574 * or remove rolling stock to or from train. 575 */ 576 protected void checkTrain(RollingStock rs) { 577 Train train = rs.getTrain(); 578 if (train != null && train.isBuilt()) { 579 if (rs.getRouteLocation() != null && 580 rs.getRouteDestination() != null && 581 rs.getTrack() == null) { 582 // no track 583 setRouteLocationAndDestination(rs, train, null, null); 584 } 585 if (rs.getRouteLocation() != null && 586 rs.getRouteDestination() != null && 587 rl != null && 588 rd != null && 589 (!rs.getRouteLocation().getName().equals(rl.getName()) || 590 !rs.getRouteDestination().getName().equals(rd.getName()))) { 591 // user changed rolling stock location or destination 592 setRouteLocationAndDestination(rs, train, null, null); 593 } 594 if (rs.getRouteLocation() != null || rs.getRouteDestination() != null) { 595 if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(getRb().getString( 596 "rsRemoveRsFromTrain"), new Object[]{rs.toString(), train.getName()}), getRb() 597 .getString("rsInRoute"), 598 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 599 // prevent rs from being picked up and delivered 600 setRouteLocationAndDestination(rs, train, null, null); 601 } 602 } else if (rl != null && rd != null && rs.getDestinationTrack() != null) { 603 if (rs.getDestinationTrack().getLocation().isStaging() && 604 !rs.getDestinationTrack().equals(train.getTerminationTrack())) { 605 log.debug("Rolling stock destination track is staging and not the same as train"); 606 JmriJOptionPane.showMessageDialog(this, 607 Bundle.getMessage("rsMustSelectSameTrack", train.getTerminationTrack() 608 .getName()), 609 Bundle.getMessage("rsStagingTrackError"), JmriJOptionPane.ERROR_MESSAGE); 610 } else if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format( 611 getRb().getString("rsAddRsToTrain"), new Object[]{rs.toString(), train.getName()}), 612 getRb().getString("rsAddManuallyToTrain"), 613 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 614 // set new pick up and set out locations 615 setRouteLocationAndDestination(rs, train, rl, rd); 616 log.debug("Add rolling stock ({}) to train ({}) route pick up {} drop {}", rs.toString(), train 617 .getName(), rl.getId(), rd.getId()); // NOI18N 618 } 619 } 620 } 621 } 622 623 protected void setRouteLocationAndDestination(RollingStock rs, Train train, RouteLocation rl, 624 RouteLocation rd) { 625 if (rs.getRouteLocation() != null || rl != null) { 626 train.setModified(true); 627 } 628 // check destination track is staging 629 if (rl == null && 630 rd == null && 631 rs.getDestinationTrack() != null && 632 rs.getDestinationTrack().getLocation().isStaging()) { 633 log.debug("Rolling stock destination track is staging"); 634 rs.setDestination(null, null); 635 } 636 rs.setRouteLocation(rl); 637 rs.setRouteDestination(rd); 638 } 639 640 protected void updateComboBoxes() { 641 log.debug("update combo boxes"); 642 locationManager.updateComboBox(locationBox); 643 locationManager.updateComboBox(destinationBox); 644 locationManager.updateComboBox(finalDestinationBox); 645 646 updateLocationComboBoxes(); 647 updateDestinationComboBoxes(); 648 } 649 650 protected boolean updateGroup(List<T> list) { 651 for (RollingStock rs : list) { 652 if (rs == _rs) { 653 continue; 654 } 655 // Location status and out of service 656 if (!ignoreStatusCheckBox.isSelected()) { 657 rs.setLocationUnknown(locationUnknownCheckBox.isSelected()); 658 rs.setOutOfService(outOfServiceCheckBox.isSelected()); 659 } 660 // update location and destination 661 if (!changeLocation(rs)) { 662 return false; 663 } 664 if (!changeDestination(rs)) { 665 return false; 666 } 667 668 if (!ignoreTrainCheckBox.isSelected()) { 669 if (trainBox.getSelectedItem() == null) { 670 rs.setTrain(null); 671 } else { 672 rs.setTrain((Train) trainBox.getSelectedItem()); 673 } 674 } 675 // set the route location and destination to match 676 rs.setRouteLocation(_rs.getRouteLocation()); 677 rs.setRouteDestination(_rs.getRouteDestination()); 678 } 679 return true; 680 } 681 682 @Override 683 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 684 log.debug("checkbox action "); 685 if (ae.getSource() == locationUnknownCheckBox) { 686 outOfServiceCheckBox.setSelected(locationUnknownCheckBox.isSelected()); 687 enableComponents(!locationUnknownCheckBox.isSelected()); 688 } 689 if (ae.getSource() == autoTrackCheckBox) { 690 updateLocationTrackComboBox(); 691 } 692 if (ae.getSource() == autoDestinationTrackCheckBox) { 693 updateDestinationTrackComboBox(); 694 } 695 if (ae.getSource() == ignoreStatusCheckBox) { 696 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 697 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 698 } 699 if (ae.getSource() == ignoreLocationCheckBox) { 700 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 701 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 702 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 703 } 704 if (ae.getSource() == ignoreDestinationCheckBox) { 705 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 706 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 707 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 708 } 709 if (ae.getSource() == ignoreFinalDestinationCheckBox) { 710 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 711 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 712 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 713 } 714 if (ae.getSource() == ignoreTrainCheckBox) { 715 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 716 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 717 } 718 } 719 720 protected void enableComponents(boolean enabled) { 721 // combo boxes 722 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 723 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 724 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 725 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 726 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 727 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 728 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 729 // checkboxes 730 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 731 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 732 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 733 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 734 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 735 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected() & enabled); 736 737 ignoreStatusCheckBox.setEnabled(enabled); 738 ignoreLocationCheckBox.setEnabled(enabled); 739 ignoreDestinationCheckBox.setEnabled(enabled); 740 ignoreFinalDestinationCheckBox.setEnabled(Setup.isCarRoutingEnabled() & enabled); 741 ignoreTrainCheckBox.setEnabled(enabled); 742 } 743 744 // location combo box 745 @Override 746 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 747 if (ae.getSource() == locationBox) { 748 updateLocationTrackComboBox(); 749 } 750 if (ae.getSource() == destinationBox || ae.getSource() == trainBox) { 751 updateDestinationTrackComboBox(); 752 } 753 } 754 755 protected void updateLocationComboBoxes() { 756 log.debug("update location combo boxes"); 757 if (_rs != null) { 758 locationBox.setSelectedItem(_rs.getLocation()); 759 } 760 // now update track combo boxes 761 updateLocationTrackComboBox(); 762 } 763 764 protected void updateLocationTrackComboBox() { 765 log.debug("update location track combobox"); 766 if (locationBox.getSelectedItem() == null) { 767 trackLocationBox.removeAllItems(); 768 } else { 769 log.debug("RollingStockFrame sees location: {}", locationBox.getSelectedItem()); 770 Location l = (Location) locationBox.getSelectedItem(); 771 l.updateComboBox(trackLocationBox, _rs, autoTrackCheckBox.isSelected(), false); 772 if (_rs != null && _rs.getLocation() != null && _rs.getLocation().equals(l) && _rs.getTrack() != null) { 773 trackLocationBox.setSelectedItem(_rs.getTrack()); 774 } 775 } 776 } 777 778 protected void updateDestinationComboBoxes() { 779 log.debug("update destination combo boxes"); 780 if (_rs != null) { 781 destinationBox.setSelectedItem(_rs.getDestination()); 782 } 783 // now update track combo boxes 784 updateDestinationTrackComboBox(); 785 } 786 787 protected void updateDestinationTrackComboBox() { 788 log.debug("update destination track combobox"); 789 if (destinationBox.getSelectedItem() == null) { 790 trackDestinationBox.removeAllItems(); 791 } else { 792 log.debug("updateDestinationTrackComboBox destination: {}, ({})", destinationBox.getSelectedItem(), 793 trackDestinationBox.getSelectedItem()); 794 Location destination = (Location) destinationBox.getSelectedItem(); 795 Track track = null; 796 if (trackDestinationBox.getSelectedItem() != null) { 797 track = (Track) trackDestinationBox.getSelectedItem(); 798 } 799 destination.updateComboBox(trackDestinationBox, _rs, autoDestinationTrackCheckBox.isSelected(), true); 800 // check for staging, add track if train is built and terminates into staging 801 if (autoDestinationTrackCheckBox.isSelected() && trainBox.getSelectedItem() != null) { 802 Train train = (Train) trainBox.getSelectedItem(); 803 if (train.isBuilt() && 804 train.getTerminationTrack() != null && 805 train.getTerminationTrack().getLocation() == destination) { 806 trackDestinationBox.addItem(train.getTerminationTrack()); 807 trackDestinationBox.setSelectedItem(track); 808 } 809 } 810 if (_rs != null && 811 _rs.getDestination() != null && 812 _rs.getDestination().equals(destination) && 813 _rs.getDestinationTrack() != null) { 814 trackDestinationBox.setSelectedItem(_rs.getDestinationTrack()); 815 } else if (track != null) { 816 trackDestinationBox.setSelectedItem(track); 817 } 818 } 819 } 820 821 protected void updateTrainComboBox() { 822 log.debug("update train combo box"); 823 trainManager.updateTrainComboBox(trainBox); 824 if (_rs != null) { 825 trainBox.setSelectedItem(_rs.getTrain()); 826 } 827 } 828 829 @Override 830 public void dispose() { 831 if (_rs != null) { 832 _rs.removePropertyChangeListener(this); 833 } 834 locationManager.removePropertyChangeListener(this); 835 trainManager.removePropertyChangeListener(this); 836 super.dispose(); 837 } 838 839 @Override 840 public void propertyChange(java.beans.PropertyChangeEvent e) { 841 log.debug("PropertyChange ({}) new: ({})", e.getPropertyName(), e.getNewValue()); 842 if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY)) { 843 updateComboBoxes(); 844 } 845 if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY)) { 846 updateTrainComboBox(); 847 } 848 if (e.getPropertyName().equals(RollingStock.TRACK_CHANGED_PROPERTY)) { 849 updateLocationComboBoxes(); 850 } 851 if (e.getPropertyName().equals(RollingStock.DESTINATION_TRACK_CHANGED_PROPERTY)) { 852 updateDestinationComboBoxes(); 853 } 854 if (e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY)) { 855 if (_rs != null) { 856 trainBox.setSelectedItem(_rs.getTrain()); 857 } 858 } 859 } 860 861 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RollingStockSetFrame.class); 862}