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 if (!status.equals(Track.OKAY)) { 480 log.debug("Can't set rs's location because of {}", status); 481 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 482 "rsCanNotLocMsg"), new Object[]{rs.toString(), status}), getRb() 483 .getString("rsCanNotLoc"), 484 JmriJOptionPane.ERROR_MESSAGE); 485 // does the user want to force the rolling stock to this track? 486 int results = JmriJOptionPane.showOptionDialog(this, MessageFormat.format(getRb() 487 .getString("rsForce"), 488 new Object[]{rs.toString(), 489 (Track) trackLocationBox.getSelectedItem()}), 490 MessageFormat.format(getRb() 491 .getString("rsOverride"), new Object[]{status}), 492 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, null, null); 493 if (results == JmriJOptionPane.YES_OPTION) { 494 log.debug("Force rolling stock to track"); 495 rs.setLocation((Location) locationBox.getSelectedItem(), (Track) trackLocationBox 496 .getSelectedItem(), RollingStock.FORCE); 497 } else { 498 return false; 499 } 500 } 501 } 502 } 503 } 504 return true; 505 } 506 507 private void loadTrain(RollingStock rs) { 508 if (!ignoreTrainCheckBox.isSelected()) { 509 if (trainBox.getSelectedItem() == null) { 510 if (rs.getTrain() != null) { 511 // prevent rs from being picked up and delivered 512 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 513 } 514 rs.setTrain(null); 515 } else { 516 Train train = (Train) trainBox.getSelectedItem(); 517 if (rs.getTrain() != null && !rs.getTrain().equals(train)) { 518 // prevent rs from being picked up and delivered 519 setRouteLocationAndDestination(rs, rs.getTrain(), null, null); 520 } 521 rs.setTrain(train); 522 } 523 } 524 } 525 526 private boolean changeDestination(RollingStock rs) { 527 if (!ignoreDestinationCheckBox.isSelected()) { 528 if (destinationBox.getSelectedItem() == null) { 529 rs.setDestination(null, null); 530 } else { 531 Track destTrack = null; 532 if (trackDestinationBox.getSelectedItem() != null) { 533 destTrack = (Track) trackDestinationBox.getSelectedItem(); 534 } 535 log.debug("changeDestination: {}, ({})", destinationBox.getSelectedItem(), 536 destTrack); 537 if (destTrack != null && 538 rs.getDestinationTrack() != destTrack && 539 destTrack.isStaging() && 540 (rs.getTrain() == null || !rs.getTrain().isBuilt())) { 541 log.debug("Destination track ({}) is staging", destTrack.getName()); 542 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsDoNotSelectStaging"), getRb() 543 .getString("rsCanNotDest"), JmriJOptionPane.ERROR_MESSAGE); 544 return false; 545 } 546 // determine is user changed the destination track and is part of train 547 if (destTrack != null && 548 rs.getDestinationTrack() != destTrack && 549 rs.getTrain() != null && 550 rs.getTrain().isBuilt() && 551 rs.getRouteLocation() != null) { 552 log.debug("Rolling stock ({}) has new track destination in built train ({})", 553 rs.toString(), rs.getTrainName()); 554 rs.getTrain().setModified(true); 555 } 556 String status = rs.setDestination((Location) destinationBox.getSelectedItem(), destTrack); 557 if (!status.equals(Track.OKAY)) { 558 log.debug("Can't set rs's destination because of {}", status); 559 JmriJOptionPane.showMessageDialog(this, MessageFormat.format(getRb().getString( 560 "rsCanNotDestMsg"), new Object[]{rs.toString(), status}), getRb().getString( 561 "rsCanNotDest"), 562 JmriJOptionPane.ERROR_MESSAGE); 563 return false; 564 } 565 } 566 } 567 return true; 568 } 569 570 /* 571 * Checks to see if rolling stock's location or destination has changed, and 572 * if so, removes the rolling stock from the train. Also allows user to add 573 * or remove rolling stock to or from train. 574 */ 575 protected void checkTrain(RollingStock rs) { 576 Train train = rs.getTrain(); 577 if (train != null && train.isBuilt()) { 578 if (rs.getRouteLocation() != null && 579 rs.getRouteDestination() != null && 580 rs.getTrack() == null) { 581 // no track 582 setRouteLocationAndDestination(rs, train, null, null); 583 } 584 if (rs.getRouteLocation() != null && 585 rs.getRouteDestination() != null && 586 rl != null && 587 rd != null && 588 (!rs.getRouteLocation().getName().equals(rl.getName()) || 589 !rs.getRouteDestination().getName().equals(rd.getName()))) { 590 // user changed rolling stock location or destination 591 setRouteLocationAndDestination(rs, train, null, null); 592 } 593 if (rs.getRouteLocation() != null || rs.getRouteDestination() != null) { 594 if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(getRb().getString( 595 "rsRemoveRsFromTrain"), new Object[]{rs.toString(), train.getName()}), getRb() 596 .getString("rsInRoute"), 597 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 598 // prevent rs from being picked up and delivered 599 setRouteLocationAndDestination(rs, train, null, null); 600 } 601 } else if (rl != null && rd != null && rs.getDestinationTrack() != null) { 602 if (rs.getDestinationTrack().getLocation().isStaging() && 603 !rs.getDestinationTrack().equals(train.getTerminationTrack())) { 604 log.debug("Rolling stock destination track is staging and not the same as train"); 605 JmriJOptionPane.showMessageDialog(this, 606 Bundle.getMessage("rsMustSelectSameTrack", train.getTerminationTrack() 607 .getName()), 608 Bundle.getMessage("rsStagingTrackError"), JmriJOptionPane.ERROR_MESSAGE); 609 } else if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format( 610 getRb().getString("rsAddRsToTrain"), new Object[]{rs.toString(), train.getName()}), 611 getRb().getString("rsAddManuallyToTrain"), 612 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 613 // set new pick up and set out locations 614 setRouteLocationAndDestination(rs, train, rl, rd); 615 log.debug("Add rolling stock ({}) to train ({}) route pick up {} drop {}", rs.toString(), train 616 .getName(), rl.getId(), rd.getId()); // NOI18N 617 } 618 } 619 } 620 } 621 622 protected void setRouteLocationAndDestination(RollingStock rs, Train train, RouteLocation rl, 623 RouteLocation rd) { 624 if (rs.getRouteLocation() != null || rl != null) { 625 train.setModified(true); 626 } 627 // check destination track is staging 628 if (rl == null && 629 rd == null && 630 rs.getDestinationTrack() != null && 631 rs.getDestinationTrack().getLocation().isStaging()) { 632 log.debug("Rolling stock destination track is staging"); 633 rs.setDestination(null, null); 634 } 635 rs.setRouteLocation(rl); 636 rs.setRouteDestination(rd); 637 } 638 639 protected void updateComboBoxes() { 640 log.debug("update combo boxes"); 641 locationManager.updateComboBox(locationBox); 642 locationManager.updateComboBox(destinationBox); 643 locationManager.updateComboBox(finalDestinationBox); 644 645 updateLocationComboBoxes(); 646 updateDestinationComboBoxes(); 647 } 648 649 protected boolean updateGroup(List<T> list) { 650 for (RollingStock rs : list) { 651 if (rs == _rs) { 652 continue; 653 } 654 // Location status and out of service 655 if (!ignoreStatusCheckBox.isSelected()) { 656 rs.setLocationUnknown(locationUnknownCheckBox.isSelected()); 657 rs.setOutOfService(outOfServiceCheckBox.isSelected()); 658 } 659 // update location and destination 660 if (!changeLocation(rs)) { 661 return false; 662 } 663 if (!changeDestination(rs)) { 664 return false; 665 } 666 667 if (!ignoreTrainCheckBox.isSelected()) { 668 if (trainBox.getSelectedItem() == null) { 669 rs.setTrain(null); 670 } else { 671 rs.setTrain((Train) trainBox.getSelectedItem()); 672 } 673 } 674 // set the route location and destination to match 675 rs.setRouteLocation(_rs.getRouteLocation()); 676 rs.setRouteDestination(_rs.getRouteDestination()); 677 } 678 return true; 679 } 680 681 @Override 682 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 683 log.debug("checkbox action "); 684 if (ae.getSource() == locationUnknownCheckBox) { 685 outOfServiceCheckBox.setSelected(locationUnknownCheckBox.isSelected()); 686 enableComponents(!locationUnknownCheckBox.isSelected()); 687 } 688 if (ae.getSource() == autoTrackCheckBox) { 689 updateLocationTrackComboBox(); 690 } 691 if (ae.getSource() == autoDestinationTrackCheckBox) { 692 updateDestinationTrackComboBox(); 693 } 694 if (ae.getSource() == ignoreStatusCheckBox) { 695 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 696 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 697 } 698 if (ae.getSource() == ignoreLocationCheckBox) { 699 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 700 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 701 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected()); 702 } 703 if (ae.getSource() == ignoreDestinationCheckBox) { 704 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 705 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 706 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected()); 707 } 708 if (ae.getSource() == ignoreFinalDestinationCheckBox) { 709 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 710 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 711 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected()); 712 } 713 if (ae.getSource() == ignoreTrainCheckBox) { 714 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 715 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected()); 716 } 717 } 718 719 protected void enableComponents(boolean enabled) { 720 // combo boxes 721 locationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 722 trackLocationBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 723 destinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 724 trackDestinationBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 725 finalDestinationBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 726 finalDestTrackBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 727 trainBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 728 // checkboxes 729 autoTrackCheckBox.setEnabled(!ignoreLocationCheckBox.isSelected() & enabled); 730 autoDestinationTrackCheckBox.setEnabled(!ignoreDestinationCheckBox.isSelected() & enabled); 731 autoFinalDestTrackCheckBox.setEnabled(!ignoreFinalDestinationCheckBox.isSelected() & enabled); 732 autoTrainCheckBox.setEnabled(!ignoreTrainCheckBox.isSelected() & enabled); 733 locationUnknownCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected()); 734 outOfServiceCheckBox.setEnabled(!ignoreStatusCheckBox.isSelected() & enabled); 735 736 ignoreStatusCheckBox.setEnabled(enabled); 737 ignoreLocationCheckBox.setEnabled(enabled); 738 ignoreDestinationCheckBox.setEnabled(enabled); 739 ignoreFinalDestinationCheckBox.setEnabled(Setup.isCarRoutingEnabled() & enabled); 740 ignoreTrainCheckBox.setEnabled(enabled); 741 } 742 743 // location combo box 744 @Override 745 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 746 if (ae.getSource() == locationBox) { 747 updateLocationTrackComboBox(); 748 } 749 if (ae.getSource() == destinationBox || ae.getSource() == trainBox) { 750 updateDestinationTrackComboBox(); 751 } 752 } 753 754 protected void updateLocationComboBoxes() { 755 log.debug("update location combo boxes"); 756 if (_rs != null) { 757 locationBox.setSelectedItem(_rs.getLocation()); 758 } 759 // now update track combo boxes 760 updateLocationTrackComboBox(); 761 } 762 763 protected void updateLocationTrackComboBox() { 764 log.debug("update location track combobox"); 765 if (locationBox.getSelectedItem() == null) { 766 trackLocationBox.removeAllItems(); 767 } else { 768 log.debug("RollingStockFrame sees location: {}", locationBox.getSelectedItem()); 769 Location l = (Location) locationBox.getSelectedItem(); 770 l.updateComboBox(trackLocationBox, _rs, autoTrackCheckBox.isSelected(), false); 771 if (_rs != null && _rs.getLocation() != null && _rs.getLocation().equals(l) && _rs.getTrack() != null) { 772 trackLocationBox.setSelectedItem(_rs.getTrack()); 773 } 774 } 775 } 776 777 protected void updateDestinationComboBoxes() { 778 log.debug("update destination combo boxes"); 779 if (_rs != null) { 780 destinationBox.setSelectedItem(_rs.getDestination()); 781 } 782 // now update track combo boxes 783 updateDestinationTrackComboBox(); 784 } 785 786 protected void updateDestinationTrackComboBox() { 787 log.debug("update destination track combobox"); 788 if (destinationBox.getSelectedItem() == null) { 789 trackDestinationBox.removeAllItems(); 790 } else { 791 log.debug("updateDestinationTrackComboBox destination: {}, ({})", destinationBox.getSelectedItem(), 792 trackDestinationBox.getSelectedItem()); 793 Location destination = (Location) destinationBox.getSelectedItem(); 794 Track track = null; 795 if (trackDestinationBox.getSelectedItem() != null) { 796 track = (Track) trackDestinationBox.getSelectedItem(); 797 } 798 destination.updateComboBox(trackDestinationBox, _rs, autoDestinationTrackCheckBox.isSelected(), true); 799 // check for staging, add track if train is built and terminates into staging 800 if (autoDestinationTrackCheckBox.isSelected() && trainBox.getSelectedItem() != null) { 801 Train train = (Train) trainBox.getSelectedItem(); 802 if (train.isBuilt() && 803 train.getTerminationTrack() != null && 804 train.getTerminationTrack().getLocation() == destination) { 805 trackDestinationBox.addItem(train.getTerminationTrack()); 806 trackDestinationBox.setSelectedItem(track); 807 } 808 } 809 if (_rs != null && 810 _rs.getDestination() != null && 811 _rs.getDestination().equals(destination) && 812 _rs.getDestinationTrack() != null) { 813 trackDestinationBox.setSelectedItem(_rs.getDestinationTrack()); 814 } else if (track != null) { 815 trackDestinationBox.setSelectedItem(track); 816 } 817 } 818 } 819 820 protected void updateTrainComboBox() { 821 log.debug("update train combo box"); 822 trainManager.updateTrainComboBox(trainBox); 823 if (_rs != null) { 824 trainBox.setSelectedItem(_rs.getTrain()); 825 } 826 } 827 828 @Override 829 public void dispose() { 830 if (_rs != null) { 831 _rs.removePropertyChangeListener(this); 832 } 833 locationManager.removePropertyChangeListener(this); 834 trainManager.removePropertyChangeListener(this); 835 super.dispose(); 836 } 837 838 @Override 839 public void propertyChange(java.beans.PropertyChangeEvent e) { 840 log.debug("PropertyChange ({}) new: ({})", e.getPropertyName(), e.getNewValue()); 841 if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY)) { 842 updateComboBoxes(); 843 } 844 if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY)) { 845 updateTrainComboBox(); 846 } 847 if (e.getPropertyName().equals(RollingStock.TRACK_CHANGED_PROPERTY)) { 848 updateLocationComboBoxes(); 849 } 850 if (e.getPropertyName().equals(RollingStock.DESTINATION_TRACK_CHANGED_PROPERTY)) { 851 updateDestinationComboBoxes(); 852 } 853 if (e.getPropertyName().equals(RollingStock.TRAIN_CHANGED_PROPERTY)) { 854 if (_rs != null) { 855 trainBox.setSelectedItem(_rs.getTrain()); 856 } 857 } 858 } 859 860 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RollingStockSetFrame.class); 861}