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