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