001package jmri.jmrit.operations.rollingstock; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004 005import java.awt.Dimension; 006import java.awt.GridBagLayout; 007import java.text.*; 008import java.util.ResourceBundle; 009 010import javax.swing.*; 011 012import jmri.*; 013import jmri.jmrit.operations.OperationsFrame; 014import jmri.jmrit.operations.OperationsXml; 015import jmri.jmrit.operations.locations.*; 016import jmri.jmrit.operations.rollingstock.cars.*; 017import jmri.jmrit.operations.rollingstock.engines.Engine; 018import jmri.jmrit.operations.rollingstock.engines.EngineTypes; 019import jmri.jmrit.operations.setup.Control; 020import jmri.jmrit.operations.setup.Setup; 021import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 022import jmri.swing.NamedBeanComboBox; 023import jmri.util.swing.JmriJOptionPane; 024 025/** 026 * Frame for edit of rolling stock. The common elements are: road, road number, 027 * type, blocking, length, location and track, groups (Kernel or Consist) 028 * weight, color, built, owner, comment. The edit engine frame currently doesn't 029 * show blocking or color. Engines and cars have different type, length, and 030 * group managers. 031 * 032 * @author Dan Boudreau Copyright (C) 2018 033 */ 034public abstract class RollingStockEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 035 036 protected static final boolean IS_SAVE = true; 037 038 protected RollingStock _rs; 039 040 protected LocationManager locationManager = InstanceManager.getDefault(LocationManager.class); 041 042 JLabel textWeightTons = new JLabel(Bundle.getMessage("WeightTons")); 043 JLabel textRfidSystemName = new JLabel(); 044 045 // major buttons 046 public JButton editRoadButton = new JButton(Bundle.getMessage("ButtonEdit")); 047 public JButton clearRoadNumberButton = new JButton(Bundle.getMessage("ButtonClear")); 048 public JButton editTypeButton = new JButton(Bundle.getMessage("ButtonEdit")); 049 public JButton editLengthButton = new JButton(Bundle.getMessage("ButtonEdit")); 050 public JButton editGroupButton = new JButton(Bundle.getMessage("ButtonEdit")); 051 public JButton editOwnerButton = new JButton(Bundle.getMessage("ButtonEdit")); 052 public JButton editColorButton = new JButton(Bundle.getMessage("ButtonEdit")); 053 054 public JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 055 public JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 056 public JButton addButton = new JButton(); // add car or locomotive 057 058 // check boxes 059 public JCheckBox autoTrackCheckBox = new JCheckBox(Bundle.getMessage("Auto")); 060 061 // text field 062 public JTextField roadNumberTextField = new JTextField(Control.max_len_string_road_number); 063 public JTextField builtTextField = new JTextField(Control.max_len_string_built_name + 3); 064 public JTextField blockingTextField = new JTextField(4); 065 public JTextField weightTextField = new JTextField(Control.max_len_string_weight_name); 066 public JTextField weightTonsTextField = new JTextField(Control.max_len_string_weight_name); 067 public JTextField commentTextField = new JTextField(35); 068 069 // text area 070 public JTextArea valueTextArea = new JTextArea(3, 35); 071 JScrollPane valueScroller = new JScrollPane(valueTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 072 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 073 074 // combo boxes 075 public JComboBox<String> roadComboBox = InstanceManager.getDefault(CarRoads.class).getComboBox(); 076 public JComboBox<String> typeComboBox = getTypeManager().getComboBox(); 077 public JComboBox<String> lengthComboBox = getLengthManager().getComboBox(); 078 public JComboBox<String> ownerComboBox = InstanceManager.getDefault(CarOwners.class).getComboBox(); 079 public JComboBox<String> colorComboBox = InstanceManager.getDefault(CarColors.class).getComboBox(); 080 public JComboBox<String> groupComboBox; 081 public JComboBox<String> modelComboBox; // for engines 082 public JComboBox<Location> locationBox = locationManager.getComboBox(); 083 public JComboBox<Track> trackLocationBox = new JComboBox<>(); 084 085 public NamedBeanComboBox<IdTag> rfidComboBox; 086 087 // panels 088 public JPanel pTypeOptions = new JPanel(); // options dependent on car or engine 089 public JPanel pGroup = new JPanel(); // Kernel or Consist 090 091 // panels for car edit 092 public JPanel pBlocking = new JPanel(); 093 public JPanel pLoad = new JPanel(); 094 public JPanel pWeightOz = new JPanel(); 095 096 // panels for engine edit 097 public JPanel pModel = new JPanel(); 098 public JPanel pPower = new JPanel(); 099 100 public RollingStockEditFrame(String title) { 101 super(title); 102 // InstanceManager = InstanceManger.getInstance(); 103 } 104 105 abstract protected RollingStockAttribute getTypeManager(); 106 107 abstract protected RollingStockAttribute getLengthManager(); 108 109 abstract protected void buttonEditActionPerformed(java.awt.event.ActionEvent ae); 110 111 abstract protected ResourceBundle getRb(); 112 113 abstract protected void save(boolean isSave); 114 115 abstract protected void delete(); 116 117 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Checks for null") 118 @Override 119 public void initComponents() { 120 121 // disable delete and save buttons 122 deleteButton.setEnabled(false); 123 saveButton.setEnabled(false); 124 125 editRoadButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace", 126 Bundle.getMessage("road"))); // initial caps for some languages i.e. German 127 editTypeButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace", 128 Bundle.getMessage("type"))); // initial caps for some languages i.e. German 129 editLengthButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace", 130 Bundle.getMessage("length"))); // initial caps for some languages i.e. German 131 editOwnerButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace", 132 Bundle.getMessage("Owner").toLowerCase())); 133 editColorButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace", 134 Bundle.getMessage("Color").toLowerCase())); 135 136 autoTrackCheckBox.setToolTipText(getRb().getString("rsTipAutoTrack")); 137 138 // create panel 139 JPanel pPanel = new JPanel(); 140 pPanel.setLayout(new BoxLayout(pPanel, BoxLayout.Y_AXIS)); 141 142 // Layout the panel by rows 143 // row 1 144 JPanel pRoad = new JPanel(); 145 pRoad.setLayout(new GridBagLayout()); 146 pRoad.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Road"))); 147 addItem(pRoad, roadComboBox, 1, 0); 148 addItem(pRoad, editRoadButton, 2, 0); 149 pPanel.add(pRoad); 150 151 // row 2 152 JPanel pRoadNumber = new JPanel(); 153 pRoadNumber.setLayout(new GridBagLayout()); 154 pRoadNumber.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RoadNumber"))); 155 addItem(pRoadNumber, roadNumberTextField, 1, 0); 156 addItem(pRoadNumber, clearRoadNumberButton, 2, 0); 157 pPanel.add(pRoadNumber); 158 159 // only engines have a model name 160 pPanel.add(pModel); 161 pModel.setVisible(false); 162 163 // row 3 164 JPanel pType = new JPanel(); 165 pType.setLayout(new GridBagLayout()); 166 pType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type"))); 167 addItem(pType, typeComboBox, 0, 0); 168 addItem(pType, editTypeButton, 1, 0); 169 170 // type options dependent on car or engine rolling stock 171 addItemWidth(pType, pTypeOptions, 3, 0, 1); 172 pPanel.add(pType); 173 174 // row 4 175 pBlocking.setLayout(new GridBagLayout()); 176 pBlocking.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutBlockingOrder"))); 177 addItem(pBlocking, blockingTextField, 0, 0); 178 blockingTextField.setText("0"); 179 pPanel.add(pBlocking); 180 pBlocking.setVisible(false); // default is blocking order not shown 181 182 // row 5 183 JPanel pLength = new JPanel(); 184 pLength.setLayout(new GridBagLayout()); 185 pLength.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Length"))); 186 addItem(pLength, lengthComboBox, 1, 0); 187 addItem(pLength, editLengthButton, 2, 0); 188 pPanel.add(pLength); 189 190 // row 6 191 JPanel pLocation = new JPanel(); 192 pLocation.setLayout(new GridBagLayout()); 193 pLocation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LocationAndTrack"))); 194 addItem(pLocation, locationBox, 1, 0); 195 addItem(pLocation, trackLocationBox, 2, 0); 196 addItem(pLocation, autoTrackCheckBox, 3, 0); 197 pPanel.add(pLocation); 198 199 // optional panel 200 JPanel pOptional = new JPanel(); 201 pOptional.setLayout(new BoxLayout(pOptional, BoxLayout.Y_AXIS)); 202 JScrollPane optionPane = new JScrollPane(pOptional); 203 optionPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptional"))); 204 205 // row 7 206 JPanel pWeight = new JPanel(); 207 pWeight.setLayout(new BoxLayout(pWeight, BoxLayout.Y_AXIS)); 208 pWeight.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Weight"))); 209 210 // weight in oz only shown for cars 211 pWeight.add(pWeightOz); 212 213 JPanel pWeightTons = new JPanel(); 214 pWeightTons.setLayout(new GridBagLayout()); 215 addItem(pWeightTons, textWeightTons, 0, 0); 216 addItem(pWeightTons, weightTonsTextField, 1, 0); 217 addItem(pWeightTons, new JLabel(), 2, 0); 218 addItem(pWeightTons, new JLabel(), 3, 0); 219 addItem(pWeightTons, new JLabel(), 4, 0); 220 pWeight.add(pWeightTons); 221 pOptional.add(pWeight); 222 223 // row 8 color 224 JPanel pColor = new JPanel(); 225 pOptional.add(pColor); 226 pColor.setLayout(new GridBagLayout()); 227 pColor.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Color"))); 228 addItem(pColor, colorComboBox, 1, 0); 229 addItem(pColor, editColorButton, 2, 0); 230 231 // row 9 for cars 232 pOptional.add(pLoad); 233 pLoad.setVisible(false); 234 235 // for engines 236 pOptional.add(pPower); 237 pPower.setVisible(false); 238 239 // row 10 240 pGroup.setLayout(new GridBagLayout()); 241 addItem(pGroup, groupComboBox, 1, 0); 242 addItem(pGroup, editGroupButton, 2, 0); 243 pOptional.add(pGroup); 244 245 // row 11 246 JPanel pBuilt = new JPanel(); 247 pBuilt.setLayout(new GridBagLayout()); 248 pBuilt.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Built"))); 249 addItem(pBuilt, builtTextField, 1, 0); 250 pOptional.add(pBuilt); 251 252 // row 12 253 JPanel pOwner = new JPanel(); 254 pOwner.setLayout(new GridBagLayout()); 255 pOwner.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Owner"))); 256 addItem(pOwner, ownerComboBox, 1, 0); 257 addItem(pOwner, editOwnerButton, 2, 0); 258 pOptional.add(pOwner); 259 260 // row 13 261 if (Setup.isValueEnabled()) { 262 JPanel pValue = new JPanel(); 263 pValue.setLayout(new GridBagLayout()); 264 pValue.setBorder(BorderFactory.createTitledBorder(Setup.getValueLabel())); 265 addItem(pValue, valueScroller, 1, 0); 266 pOptional.add(pValue); 267 268 // adjust text area width based on window size 269 adjustTextAreaColumnWidth(valueScroller, valueTextArea); 270 } 271 272 // row 14 273 IdTagManager tagManager = InstanceManager.getNullableDefault(IdTagManager.class); 274 if (Setup.isRfidEnabled() && tagManager != null) { 275 JPanel pRfid = new JPanel(); 276 pRfid.setLayout(new GridBagLayout()); 277 pRfid.setBorder(BorderFactory.createTitledBorder(Setup.getRfidLabel())); 278 rfidComboBox = new NamedBeanComboBox<IdTag>(tagManager); 279 rfidComboBox.setAllowNull(true); 280 rfidComboBox.setToolTipText(Bundle.getMessage("TipIdTag")); 281 addItem(pRfid, rfidComboBox, 0, 0); 282 addItem(pRfid, textRfidSystemName, 1, 0); 283 pOptional.add(pRfid); 284 } 285 286 // row 15 287 JPanel pComment = new JPanel(); 288 pComment.setLayout(new GridBagLayout()); 289 pComment.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Comment"))); 290 addItem(pComment, commentTextField, 1, 0); 291 pOptional.add(pComment); 292 293 // button panel 294 JPanel pButtons = new JPanel(); 295 pButtons.setLayout(new GridBagLayout()); 296 addItem(pButtons, deleteButton, 0, 25); 297 addItem(pButtons, addButton, 1, 25); 298 addItem(pButtons, saveButton, 3, 25); 299 300 // add panels 301 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 302 getContentPane().add(pPanel); 303 getContentPane().add(optionPane); 304 getContentPane().add(pButtons); 305 306 // setup buttons 307 addEditButtonAction(editRoadButton); 308 addEditButtonAction(editTypeButton); 309 addEditButtonAction(editLengthButton); 310 addEditButtonAction(editGroupButton); 311 addEditButtonAction(editOwnerButton); 312 addEditButtonAction(editColorButton); 313 314 addButtonAction(clearRoadNumberButton); 315 addButtonAction(deleteButton); 316 addButtonAction(addButton); 317 addButtonAction(saveButton); 318 319 // setup combobox 320 addComboBoxAction(typeComboBox); 321 addComboBoxAction(lengthComboBox); 322 addComboBoxAction(locationBox); 323 324 addCheckBoxAction(autoTrackCheckBox); 325 autoTrackCheckBox.setEnabled(false); 326 327 // get notified if combo box gets modified 328 addPropertyChangeListeners(); 329 330 initMinimumSize(new Dimension(Control.panelWidth500, Control.panelHeight500)); 331 } 332 333 protected void load(RollingStock rs) { 334 _rs = rs; 335 336 // engines and cars share the same road database 337 if (!InstanceManager.getDefault(CarRoads.class).containsName(rs.getRoadName())) { 338 if (JmriJOptionPane.showConfirmDialog(this, 339 Bundle.getMessage("roadNameNotExist", rs.getRoadName()), 340 Bundle.getMessage("addRoad"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 341 InstanceManager.getDefault(CarRoads.class).addName(rs.getRoadName()); 342 } 343 } 344 roadComboBox.setSelectedItem(rs.getRoadName()); 345 346 roadNumberTextField.setText(rs.getNumber()); 347 348 if (!getTypeManager().containsName(rs.getTypeName())) { 349 if (JmriJOptionPane.showConfirmDialog(this, 350 Bundle.getMessage("typeNameNotExist", rs.getTypeName()), 351 Bundle.getMessage("addType"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 352 getTypeManager().addName(rs.getTypeName()); 353 } 354 } 355 typeComboBox.setSelectedItem(rs.getTypeName()); 356 blockingTextField.setText(Integer.toString(rs.getBlocking())); 357 358 if (!getLengthManager().containsName(rs.getLength())) { 359 if (JmriJOptionPane.showConfirmDialog(this, 360 Bundle.getMessage("lengthNameNotExist", rs.getLength()), 361 Bundle.getMessage("addLength"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 362 getLengthManager().addName(rs.getLength()); 363 } 364 } 365 // } 366 lengthComboBox.setSelectedItem(rs.getLength()); 367 368 weightTextField.setText(rs.getWeight()); 369 weightTonsTextField.setText(rs.getWeightTons()); 370 locationBox.setSelectedItem(rs.getLocation()); 371 updateTrackLocationBox(); 372 373 builtTextField.setText(rs.getBuilt()); 374 375 // Engines and cars share the owner database 376 if (!InstanceManager.getDefault(CarOwners.class).containsName(rs.getOwnerName())) { 377 if (JmriJOptionPane.showConfirmDialog(this, 378 Bundle.getMessage("ownerNameNotExist", rs.getOwnerName()), 379 Bundle.getMessage("addOwner"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 380 InstanceManager.getDefault(CarOwners.class).addName(rs.getOwnerName()); 381 } 382 } 383 ownerComboBox.setSelectedItem(rs.getOwnerName()); 384 385 // color attribute 386 if (!InstanceManager.getDefault(CarColors.class).containsName(rs.getColorName())) { 387 if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("colorNameNotExist", 388 rs.getColorName()), Bundle.getMessage("addColor"), 389 JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 390 InstanceManager.getDefault(CarColors.class).addName(rs.getColorName()); 391 } 392 } 393 colorComboBox.setSelectedItem(rs.getColorName()); 394 395 commentTextField.setText(rs.getComment()); 396 valueTextArea.setText(rs.getValue()); 397 if (rfidComboBox != null) { 398 rfidComboBox.setSelectedItem(rs.getIdTag()); 399 textRfidSystemName.setText(rs.getRfid()); 400 } 401 // enable delete and save buttons 402 deleteButton.setEnabled(true); 403 saveButton.setEnabled(true); 404 autoTrackCheckBox.setEnabled(true); 405 } 406 407 @Override 408 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 409 if (ae.getSource() == typeComboBox && typeComboBox.getSelectedItem() != null) { 410 // turn off auto for location tracks 411 autoTrackCheckBox.setSelected(false); 412 autoTrackCheckBox.setEnabled(false); 413 updateTrackLocationBox(); 414 } 415 if (ae.getSource() == locationBox) { 416 updateTrackLocationBox(); 417 } 418 } 419 420 @Override 421 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 422 if (ae.getSource() == autoTrackCheckBox) { 423 updateTrackLocationBox(); 424 } 425 } 426 427 // Save, Delete, Add, Clear, Calculate, Edit Load buttons 428 @Override 429 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 430 if (ae.getSource() == saveButton) { 431 // log.debug("car save button pressed"); 432 if (!check(_rs)) { 433 return; 434 } 435 save(IS_SAVE); 436 // save car file 437 OperationsXml.save(); 438 if (Setup.isCloseWindowOnSaveEnabled()) { 439 dispose(); 440 } 441 } 442 if (ae.getSource() == addButton) { 443 if (!check(null)) { 444 return; 445 } 446 447 // enable delete and save buttons 448 deleteButton.setEnabled(true); 449 saveButton.setEnabled(true); 450 451 save(!IS_SAVE); 452 // save car file 453 OperationsXml.save(); 454 } 455 if (ae.getSource() == deleteButton) { 456 log.debug("rolling stock delete button activated"); 457 // disable delete and save buttons 458 deleteButton.setEnabled(false); 459 saveButton.setEnabled(false); 460 if (_rs != null) { 461 _rs.removePropertyChangeListener(this); 462 } 463 delete(); 464 _rs = null; 465 OperationsXml.save(); 466 } 467 if (ae.getSource() == clearRoadNumberButton) { 468 roadNumberTextField.setText(""); 469 roadNumberTextField.requestFocus(); 470 } 471 } 472 473 protected void updateTrackLocationBox() { 474 if (locationBox.getSelectedItem() == null) { 475 trackLocationBox.removeAllItems(); 476 } else { 477 log.debug("Update tracks for location: {}", locationBox.getSelectedItem()); 478 Location loc = ((Location) locationBox.getSelectedItem()); 479 loc.updateComboBox(trackLocationBox, _rs, autoTrackCheckBox.isSelected(), false); 480 if (_rs != null && _rs.getLocation() == loc) { 481 trackLocationBox.setSelectedItem(_rs.getTrack()); 482 } 483 } 484 } 485 486 protected boolean check(RollingStock rs) { 487 String roadNum = roadNumberTextField.getText(); 488 // hyphen feature needs at least one character to work properly 489 if (roadNum.contains(TrainCommon.HYPHEN) && roadNum.split(TrainCommon.HYPHEN).length == 0) { 490 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("HyphenFeature"), Bundle.getMessage("roadNumNG"), 491 JmriJOptionPane.ERROR_MESSAGE); 492 return false; 493 } 494 // ignore characters after hyphen for field length 495 String rNum = TrainCommon.splitString(roadNum); 496 if (rNum.length() > Control.max_len_string_road_number) { 497 JmriJOptionPane.showMessageDialog(this, 498 MessageFormat.format(getRb().getString("RoadNumMustBeLess"), 499 new Object[]{Control.max_len_string_road_number + 1}), 500 getRb().getString("RoadNumTooLong"), JmriJOptionPane.ERROR_MESSAGE); 501 return false; 502 } 503 if (!OperationsXml.checkFileName(roadNum)) { 504 JmriJOptionPane.showMessageDialog(this, 505 Bundle.getMessage("NameResChar") + NEW_LINE + Bundle.getMessage("ReservedChar"), 506 Bundle.getMessage("roadNumNG"), JmriJOptionPane.ERROR_MESSAGE); 507 return false; 508 } 509 // check rolling stock's weight in tons has proper format 510 if (!weightTonsTextField.getText().trim().isEmpty()) { 511 try { 512 Integer.parseInt(weightTonsTextField.getText()); 513 } catch (Exception e) { 514 JmriJOptionPane.showMessageDialog(this, getRb().getString("WeightFormatTon"), 515 getRb().getString("WeightTonError"), JmriJOptionPane.ERROR_MESSAGE); 516 return false; 517 } 518 } 519 return true; 520 } 521 522 protected <T extends RollingStock> boolean save(RollingStockManager<T> manager, boolean isSave) { 523 // if the rolling stock's road or number changes, it needs a new id 524 if (isSave && 525 _rs != null && 526 (!_rs.getRoadName().equals(roadComboBox.getSelectedItem()) || 527 !_rs.getNumber().equals(roadNumberTextField.getText()))) { 528 String road = (String) roadComboBox.getSelectedItem(); 529 String number = roadNumberTextField.getText(); 530 int results = JmriJOptionPane.showOptionDialog(this, 531 Bundle.getMessage("rsAreYouSure", _rs.getRoadName(), _rs.getNumber(), road, number), 532 Bundle.getMessage("rsChangeNumberRoad"), JmriJOptionPane.YES_NO_OPTION, 533 JmriJOptionPane.QUESTION_MESSAGE, null, null, null); 534 if (results != JmriJOptionPane.YES_OPTION) { 535 return false; 536 } 537 538 _rs.setRoadName(road); 539 _rs.setNumber(number); 540 } 541 if (_rs == null || 542 !_rs.getRoadName().equals(roadComboBox.getSelectedItem()) || 543 !_rs.getNumber().equals(roadNumberTextField.getText())) { 544 _rs = manager.newRS((String) roadComboBox.getSelectedItem(), roadNumberTextField.getText()); 545 _rs.addPropertyChangeListener(this); 546 } 547 // engine model must be set before type, length, weight and HP 548 if (Engine.class.isInstance(_rs) && modelComboBox.getSelectedItem() != null) { 549 ((Engine) _rs).setModel((String) modelComboBox.getSelectedItem()); 550 } 551 if (typeComboBox.getSelectedItem() != null) { 552 _rs.setTypeName((String) typeComboBox.getSelectedItem()); 553 } 554 if (colorComboBox.getSelectedItem() != null) { 555 _rs.setColorName((String) colorComboBox.getSelectedItem()); 556 } 557 558 int blocking = RollingStock.DEFAULT_BLOCKING_ORDER; 559 try { 560 blocking = Integer.parseInt(blockingTextField.getText()); 561 // only allow numbers between -100 and 100 562 if (blocking < -RollingStock.MAX_BLOCKING_ORDER || blocking > RollingStock.MAX_BLOCKING_ORDER) { 563 blocking = RollingStock.DEFAULT_BLOCKING_ORDER; 564 } 565 } catch (Exception e) { 566 log.warn("Blocking must be a number between -{} and {}", RollingStock.MAX_BLOCKING_ORDER, 567 RollingStock.MAX_BLOCKING_ORDER); 568 } 569 blockingTextField.setText(Integer.toString(blocking)); 570 571 if (lengthComboBox.getSelectedItem() != null) { 572 _rs.setLength((String) lengthComboBox.getSelectedItem()); 573 } 574 try { 575 _rs.setWeight(NumberFormat.getNumberInstance().parse(weightTextField.getText()).toString()); 576 } catch (ParseException e1) { 577 log.debug("Weight not a number"); 578 } 579 _rs.setWeightTons(weightTonsTextField.getText()); 580 _rs.setBuilt(builtTextField.getText()); 581 if (ownerComboBox.getSelectedItem() != null) { 582 _rs.setOwnerName((String) ownerComboBox.getSelectedItem()); 583 } 584 _rs.setComment(commentTextField.getText()); 585 _rs.setValue(valueTextArea.getText()); 586 if (rfidComboBox != null) { 587 // save the IdTag for this rolling stock 588 _rs.setIdTag(rfidComboBox.getSelectedItem()); 589 textRfidSystemName.setText(_rs.getRfid()); 590 } 591 autoTrackCheckBox.setEnabled(true); 592 return true; 593 } 594 595 protected void checkAndSetLocationAndTrack(RollingStock rs) { 596 if (locationBox.getSelectedItem() != null && trackLocationBox.getSelectedItem() == null) { 597 JmriJOptionPane.showMessageDialog(this, getRb().getString("rsFullySelect"), 598 getRb().getString("rsCanNotLoc"), 599 JmriJOptionPane.ERROR_MESSAGE); 600 // update location only if it has changed 601 } else if (rs.getLocation() == null || 602 rs.getLocation() != locationBox.getSelectedItem() || 603 rs.getTrack() == null || 604 rs.getTrack() != trackLocationBox.getSelectedItem()) { 605 setLocationAndTrack(rs); 606 } 607 } 608 609 protected void setLocationAndTrack(RollingStock rs) { 610 if (locationBox.getSelectedItem() == null) { 611 rs.setLocation(null, null); 612 } else { 613 rs.setLastRouteId(RollingStock.NONE); // clear last route id 614 rs.setLastTrain(null); // clear last train 615 String status = rs.setLocation((Location) locationBox.getSelectedItem(), 616 (Track) trackLocationBox.getSelectedItem()); 617 if (!status.equals(Track.OKAY)) { 618 log.debug("Can't set rolling stock's location because of {}", status); 619 JmriJOptionPane.showMessageDialog(this, 620 MessageFormat.format(getRb().getString("rsCanNotLocMsg"), 621 new Object[]{rs.toString(), status}), 622 getRb().getString("rsCanNotLoc"), JmriJOptionPane.ERROR_MESSAGE); 623 // does the user want to force the rolling stock to this track? 624 int results = JmriJOptionPane.showOptionDialog(this, 625 MessageFormat.format(getRb().getString("rsForce"), 626 new Object[]{rs.toString(), (Track) trackLocationBox.getSelectedItem()}), 627 MessageFormat.format(getRb().getString("rsOverride"), new Object[]{status}), 628 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, null, null); 629 if (results == JmriJOptionPane.YES_OPTION) { 630 log.debug("Force rolling stock to track"); 631 rs.setLocation((Location) locationBox.getSelectedItem(), (Track) trackLocationBox.getSelectedItem(), 632 RollingStock.FORCE); 633 } 634 } 635 } 636 } 637 638 // for the AttributeEditFrame edit buttons 639 protected void addEditButtonAction(JButton b) { 640 b.addActionListener(new java.awt.event.ActionListener() { 641 @Override 642 public void actionPerformed(java.awt.event.ActionEvent e) { 643 buttonEditActionPerformed(e); 644 } 645 }); 646 } 647 648 @Override 649 public void dispose() { 650 removePropertyChangeListeners(); 651 super.dispose(); 652 } 653 654 protected void addPropertyChangeListeners() { 655 InstanceManager.getDefault(CarRoads.class).addPropertyChangeListener(this); 656 getTypeManager().addPropertyChangeListener(this); 657 getLengthManager().addPropertyChangeListener(this); 658 InstanceManager.getDefault(CarOwners.class).addPropertyChangeListener(this); 659 InstanceManager.getDefault(CarColors.class).addPropertyChangeListener(this); 660 locationManager.addPropertyChangeListener(this); 661 } 662 663 protected void removePropertyChangeListeners() { 664 InstanceManager.getDefault(CarRoads.class).removePropertyChangeListener(this); 665 getTypeManager().removePropertyChangeListener(this); 666 getLengthManager().removePropertyChangeListener(this); 667 InstanceManager.getDefault(CarOwners.class).removePropertyChangeListener(this); 668 InstanceManager.getDefault(CarColors.class).removePropertyChangeListener(this); 669 locationManager.removePropertyChangeListener(this); 670 } 671 672 @Override 673 public void propertyChange(java.beans.PropertyChangeEvent e) { 674 if (e.getPropertyName().equals(CarRoads.CARROADS_CHANGED_PROPERTY)) { 675 InstanceManager.getDefault(CarRoads.class).updateComboBox(roadComboBox); 676 if (_rs != null) { 677 roadComboBox.setSelectedItem(_rs.getRoadName()); 678 } 679 } 680 if (e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY) || 681 e.getPropertyName().equals(EngineTypes.ENGINETYPES_CHANGED_PROPERTY)) { 682 getTypeManager().updateComboBox(typeComboBox); 683 if (_rs != null) { 684 typeComboBox.setSelectedItem(_rs.getTypeName()); 685 } 686 } 687 if (e.getPropertyName().equals(CarOwners.CAROWNERS_CHANGED_PROPERTY)) { 688 InstanceManager.getDefault(CarOwners.class).updateComboBox(ownerComboBox); 689 if (_rs != null) { 690 ownerComboBox.setSelectedItem(_rs.getOwnerName()); 691 } 692 } 693 if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY) || 694 e.getPropertyName().equals(RollingStock.TRACK_CHANGED_PROPERTY)) { 695 InstanceManager.getDefault(LocationManager.class).updateComboBox(locationBox); 696 updateTrackLocationBox(); 697 if (_rs != null && _rs.getLocation() != null) { 698 locationBox.setSelectedItem(_rs.getLocation()); 699 } 700 } 701 if (e.getPropertyName().equals(CarColors.CARCOLORS_CHANGED_PROPERTY)) { 702 InstanceManager.getDefault(CarColors.class).updateComboBox(colorComboBox); 703 if (_rs != null) { 704 colorComboBox.setSelectedItem(_rs.getColorName()); 705 } 706 } 707 } 708 709 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RollingStockEditFrame.class); 710}