001package jmri.jmrit.operations.rollingstock.cars.tools; 002 003import java.awt.Dimension; 004import java.awt.GridBagLayout; 005 006import javax.swing.*; 007 008import jmri.InstanceManager; 009import jmri.jmrit.operations.OperationsFrame; 010import jmri.jmrit.operations.OperationsXml; 011import jmri.jmrit.operations.locations.LocationManager; 012import jmri.jmrit.operations.locations.schedules.ScheduleManager; 013import jmri.jmrit.operations.rollingstock.cars.*; 014import jmri.jmrit.operations.setup.Control; 015import jmri.jmrit.operations.setup.Setup; 016import jmri.jmrit.operations.trains.TrainManager; 017import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 018import jmri.util.swing.JmriJOptionPane; 019 020/** 021 * Frame for adding and editing the car load attribute for operations. 022 * 023 * @author Daniel Boudreau Copyright (C) 2009, 2010, 2011, 2023 024 */ 025public class CarLoadEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 026 027 CarLoads carLoads = InstanceManager.getDefault(CarLoads.class); 028 CarTypes carTypes = InstanceManager.getDefault(CarTypes.class); 029 030 // labels 031 JLabel textSep = new JLabel(); 032 JLabel quanity = new JLabel("0"); 033 034 // major buttons 035 JButton addButton = new JButton(Bundle.getMessage("Add")); 036 JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 037 JButton replaceButton = new JButton(Bundle.getMessage("Replace")); 038 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 039 040 // combo boxes 041 JComboBox<String> typeComboBox = carTypes.getComboBox(); 042 JComboBox<String> loadComboBox; 043 JComboBox<String> priorityComboBox = carLoads.getPriorityComboBox(); 044 JComboBox<String> hazardousComboBox = carLoads.getHazardousComboBox(); 045 JComboBox<String> loadTypeComboBox = carLoads.getLoadTypesComboBox(); 046 047 // check boxes 048 JCheckBox allTypesCheckBox = new JCheckBox(Bundle.getMessage("All")); 049 050 // text boxes 051 JTextField addTextBox = new JTextField(Control.max_len_string_attibute); 052 JTextField pickupCommentTextField = new JTextField(35); 053 JTextField dropCommentTextField = new JTextField(35); 054 055 public CarLoadEditFrame() { 056 super(Bundle.getMessage("TitleCarEditLoad")); 057 } 058 059 String _type; // car type name 060 boolean menuActive = false; 061 062 public void initComponents(String type, String selectedItem) { 063 064 getContentPane().removeAll(); 065 066 _type = type; 067 typeComboBox.setSelectedItem(_type); 068 069 loadComboBox = carLoads.getComboBox(_type); 070 carLoads.addPropertyChangeListener(this); 071 loadComboBox.setSelectedItem(selectedItem); 072 // user adding new load name? 073 if (!loadComboBox.getSelectedItem().equals(selectedItem)) { 074 addTextBox.setText(selectedItem); 075 } 076 updateLoadType(); 077 updatePriority(); 078 updateHazardous(); 079 080 // general GUI config 081 quanity.setVisible(showQuanity); 082 083 // car type panel 084 JPanel pType = new JPanel(); 085 pType.setLayout(new GridBagLayout()); 086 pType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type"))); 087 addItem(pType, typeComboBox, 0, 0); 088 addItem(pType, allTypesCheckBox, 1, 0); 089 090 allTypesCheckBox.setToolTipText(Bundle.getMessage("TipCarLoadAll")); 091 092 // load panel 093 JPanel pLoad = new JPanel(); 094 pLoad.setLayout(new GridBagLayout()); 095 pLoad.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Load"))); 096 097 // row 2 098 addItem(pLoad, addTextBox, 2, 2); 099 addItem(pLoad, addButton, 3, 2); 100 101 // row 3 102 addItem(pLoad, quanity, 1, 3); 103 addItem(pLoad, loadComboBox, 2, 3); 104 addItem(pLoad, deleteButton, 3, 3); 105 106 // row 4 107 addItem(pLoad, replaceButton, 3, 4); 108 109 deleteButton.setToolTipText(Bundle.getMessage("TipDeleteAttributeName", 110 Bundle.getMessage("Load"))); 111 addButton.setToolTipText(Bundle.getMessage("TipAddAttributeName", 112 Bundle.getMessage("Load"))); 113 replaceButton.setToolTipText(Bundle.getMessage("TipReplaceAttributeName", 114 Bundle.getMessage("Load"))); 115 116 // row 6 117 JPanel pLoadType = new JPanel(); 118 pLoadType.setLayout(new BoxLayout(pLoadType, BoxLayout.Y_AXIS)); 119 pLoadType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLoadType"))); 120 addItem(pLoadType, loadTypeComboBox, 0, 0); 121 122 // row 8 123 JPanel pPriority = new JPanel(); 124 pPriority.setLayout(new BoxLayout(pPriority, BoxLayout.Y_AXIS)); 125 pPriority.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPriority"))); 126 addItem(pPriority, priorityComboBox, 0, 0); 127 128 // row 9 129 JPanel pHazardous = new JPanel(); 130 pHazardous.setLayout(new BoxLayout(pHazardous, BoxLayout.Y_AXIS)); 131 pHazardous.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Hazardous"))); 132 addItem(pHazardous, hazardousComboBox, 0, 0); 133 134 // row 10 135 // optional panel 136 JPanel pOptionalPickup = new JPanel(); 137 pOptionalPickup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptionalPickup"))); 138 addItem(pOptionalPickup, pickupCommentTextField, 0, 0); 139 140 // row 12 141 JPanel pOptionalDrop = new JPanel(); 142 pOptionalDrop.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptionalDrop"))); 143 addItem(pOptionalDrop, dropCommentTextField, 0, 0); 144 145 // row 14 146 JPanel pControl = new JPanel(); 147 pControl.setLayout(new BoxLayout(pControl, BoxLayout.Y_AXIS)); 148 addItem(pControl, saveButton, 0, 0); 149 150 // add panels 151 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 152 getContentPane().add(pType); 153 getContentPane().add(pLoad); 154 getContentPane().add(pLoadType); 155 getContentPane().add(pPriority); 156 getContentPane().add(pHazardous); 157 getContentPane().add(pOptionalPickup); 158 getContentPane().add(pOptionalDrop); 159 getContentPane().add(pControl); 160 161 addButtonAction(addButton); 162 addButtonAction(deleteButton); 163 addButtonAction(replaceButton); 164 addButtonAction(saveButton); 165 166 addComboBoxAction(typeComboBox); 167 addComboBoxAction(loadComboBox); 168 169 addCheckBoxAction(allTypesCheckBox); 170 171 updateCarCommentFields(); 172 173 enableButtons(); 174 175 // build menu 176 JMenuBar menuBar = new JMenuBar(); 177 JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools")); 178 toolMenu.add(new CarLoadAttributeAction(this)); 179 toolMenu.add(new PrintCarLoadsAction(true)); 180 toolMenu.add(new PrintCarLoadsAction(false)); 181 menuBar.add(toolMenu); 182 setJMenuBar(menuBar); 183 // add help menu to window 184 addHelpMenu("package.jmri.jmrit.operations.Operations_EditCarLoads", true); // NOI18N 185 186 initMinimumSize(new Dimension(Control.panelWidth400, Control.panelHeight500)); 187 } 188 189 // add, delete, replace, and save buttons 190 @Override 191 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 192 String loadName = addTextBox.getText().trim(); 193 if (ae.getSource() == addButton || ae.getSource() == replaceButton) { 194 if (!checkLoadName(loadName)) { 195 return; 196 } 197 } 198 if (ae.getSource() == addButton) { 199 addLoadName(loadName); 200 } 201 if (ae.getSource() == deleteButton) { 202 deleteLoadName(); 203 } 204 if (ae.getSource() == replaceButton) { 205 replaceLoadName(loadName); 206 } 207 if (ae.getSource() == saveButton) { 208 saveLoadName(); 209 OperationsXml.save(); // save all files that have been modified; 210 if (Setup.isCloseWindowOnSaveEnabled()) { 211 dispose(); 212 } 213 } 214 } 215 216 private boolean checkLoadName(String loadName) { 217 if (loadName.equals(NONE)) { 218 return false; 219 } 220 String[] splitLoadName = loadName.split(TrainCommon.HYPHEN); 221 // hyphen feature needs at least one character to work properly 222 if (loadName.contains(TrainCommon.HYPHEN)) { 223 if (splitLoadName.length == 0) { 224 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("HyphenFeature"), 225 Bundle.getMessage("canNotAdd", Bundle.getMessage("load")), 226 JmriJOptionPane.ERROR_MESSAGE); 227 return false; 228 } 229 } 230 if (splitLoadName[0].length() > Control.max_len_string_attibute) { 231 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carAttribute", 232 Control.max_len_string_attibute), Bundle.getMessage("canNotUseLoadName"), 233 JmriJOptionPane.ERROR_MESSAGE); 234 return false; 235 } 236 // can't have the " & " as part of the load name 237 if (loadName.contains(CarLoad.SPLIT_CHAR)) { 238 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carNameNoAndChar", 239 CarLoad.SPLIT_CHAR), Bundle.getMessage("canNotUseLoadName"), 240 JmriJOptionPane.ERROR_MESSAGE); 241 return false; 242 } 243 return true; 244 } 245 246 @Override 247 protected void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 248 log.debug("Combo box action"); 249 if (ae.getSource() == typeComboBox) { 250 _type = (String) typeComboBox.getSelectedItem(); 251 updateLoadComboBox(); 252 enableButtons(); 253 } 254 updateCarQuanity(); 255 updateLoadType(); 256 updatePriority(); 257 updateHazardous(); 258 updateCarCommentFields(); 259 } 260 261 @Override 262 protected void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 263 typeComboBox.setEnabled(!allTypesCheckBox.isSelected()); 264 } 265 266 private void addLoadName(String loadName) { 267 if (allTypesCheckBox.isSelected()) { 268 for (String type : carTypes.getNames()) { 269 carLoads.addName(type, loadName); 270 } 271 } else { 272 carLoads.addName(_type, loadName); 273 } 274 } 275 276 private void deleteLoadName() { 277 String deleteLoad = (String) loadComboBox.getSelectedItem(); 278 if (deleteLoad.equals(carLoads.getDefaultEmptyName()) || deleteLoad.equals(carLoads.getDefaultLoadName())) { 279 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carLoadDefault"), Bundle 280 .getMessage("canNotDelete", Bundle.getMessage("Load")), 281 JmriJOptionPane.ERROR_MESSAGE); 282 return; 283 } 284 if (allTypesCheckBox.isSelected()) { 285 for (String type : carTypes.getNames()) { 286 replaceLoad(type, deleteLoad, null); 287 carLoads.deleteName(type, deleteLoad); 288 } 289 } else { 290 replaceLoad(_type, deleteLoad, null); 291 carLoads.deleteName(_type, deleteLoad); 292 } 293 } 294 295 private void replaceLoadName(String loadName) { 296 String oldLoadName = (String) loadComboBox.getSelectedItem(); 297 if (oldLoadName.equals(carLoads.getDefaultEmptyName())) { 298 if (JmriJOptionPane.showConfirmDialog(this, 299 Bundle.getMessage("replaceDefaultEmpty", 300 oldLoadName, loadName), 301 Bundle.getMessage("replaceAll"), 302 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 303 return; 304 } 305 // don't allow the default names for load and empty to be the 306 // same 307 if (loadName.equals(carLoads.getDefaultEmptyName()) || loadName.equals(carLoads.getDefaultLoadName())) { 308 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carDefault"), Bundle 309 .getMessage("canNotReplace", Bundle.getMessage("Load")), 310 JmriJOptionPane.ERROR_MESSAGE); 311 return; 312 } 313 carLoads.setDefaultEmptyName(loadName); 314 replaceAllLoads(oldLoadName, loadName); 315 return; 316 } 317 if (oldLoadName.equals(carLoads.getDefaultLoadName())) { 318 if (JmriJOptionPane.showConfirmDialog(this, 319 Bundle.getMessage("replaceDefaultLoad", 320 oldLoadName, loadName), 321 Bundle.getMessage("replaceAll"), 322 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 323 return; 324 } 325 // don't allow the default names for load and empty to be the 326 // same 327 if (loadName.equals(carLoads.getDefaultEmptyName()) || loadName.equals(carLoads.getDefaultLoadName())) { 328 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carDefault"), Bundle 329 .getMessage("canNotReplace", Bundle.getMessage("Load")), 330 JmriJOptionPane.ERROR_MESSAGE); 331 return; 332 } 333 carLoads.setDefaultLoadName(loadName); 334 replaceAllLoads(oldLoadName, loadName); 335 return; 336 } 337 if (JmriJOptionPane.showConfirmDialog(this, 338 Bundle.getMessage("replaceMsg", 339 oldLoadName, loadName), 340 Bundle.getMessage("replaceAll"), 341 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 342 return; 343 } 344 if (oldLoadName.equals(loadName)) { 345 return; // do nothing 346 } 347 // ComboBoxes get deselected during the addName operation 348 String loadType = carLoads.getLoadType(_type, oldLoadName); 349 String loadPriority = carLoads.getPriority(_type, oldLoadName); 350 boolean isHazardous = carLoads.isHazardous(_type, oldLoadName); 351 String pickupComment = carLoads.getPickupComment(_type, oldLoadName); 352 String dropComment = carLoads.getDropComment(_type, oldLoadName); 353 354 if (allTypesCheckBox.isSelected()) { 355 for (String type : carTypes.getNames()) { 356 carLoads.addName(type, loadName); 357 carLoads.setLoadType(type, loadName, loadType); 358 carLoads.setPriority(type, loadName, loadPriority); 359 carLoads.setHazardous(type, loadName, isHazardous); 360 carLoads.setPickupComment(type, loadName, pickupComment); 361 carLoads.setDropComment(type, loadName, dropComment); 362 replaceLoad(type, oldLoadName, loadName); 363 carLoads.deleteName(type, oldLoadName); 364 } 365 } else { 366 carLoads.addName(_type, loadName); 367 carLoads.setLoadType(_type, loadName, loadType); 368 carLoads.setPriority(_type, loadName, loadPriority); 369 carLoads.setHazardous(_type, loadName, isHazardous); 370 carLoads.setPickupComment(_type, loadName, pickupComment); 371 carLoads.setDropComment(_type, loadName, dropComment); 372 replaceLoad(_type, oldLoadName, loadName); 373 carLoads.deleteName(_type, oldLoadName); 374 } 375 } 376 377 private void saveLoadName() { 378 if (allTypesCheckBox.isSelected()) { 379 for (String type : carTypes.getNames()) { 380 saveLoadName(type); 381 } 382 } else { 383 saveLoadName(_type); 384 } 385 } 386 387 private void saveLoadName(String type) { 388 carLoads.setLoadType(type, (String) loadComboBox.getSelectedItem(), (String) loadTypeComboBox 389 .getSelectedItem()); 390 carLoads.setPriority(type, (String) loadComboBox.getSelectedItem(), 391 (String) priorityComboBox.getSelectedItem()); 392 carLoads.setHazardous(type, (String) loadComboBox.getSelectedItem(), 393 hazardousComboBox.getSelectedItem().equals(Bundle.getMessage("ButtonYes"))); 394 carLoads.setPickupComment(type, (String) loadComboBox.getSelectedItem(), pickupCommentTextField.getText()); 395 carLoads.setDropComment(type, (String) loadComboBox.getSelectedItem(), dropCommentTextField.getText()); 396 } 397 398 // replace load name for all car types 399 private void replaceAllLoads(String oldLoad, String newLoad) { 400 for (String type : carTypes.getNames()) { 401 // need to delete when changing default load names 402 if (carLoads.containsName(type, newLoad)) { 403 carLoads.deleteName(type, newLoad); 404 } 405 carLoads.addName(type, newLoad); 406 replaceLoad(type, oldLoad, newLoad); 407 carLoads.deleteName(type, oldLoad); 408 } 409 } 410 411 private void replaceLoad(String type, String oldLoad, String newLoad) { 412 // adjust all cars 413 InstanceManager.getDefault(CarManager.class).replaceLoad(type, oldLoad, newLoad); 414 // now adjust schedules 415 InstanceManager.getDefault(ScheduleManager.class).replaceLoad(type, oldLoad, newLoad); 416 // now adjust trains 417 InstanceManager.getDefault(TrainManager.class).replaceLoad(type, oldLoad, newLoad); 418 // now adjust tracks 419 InstanceManager.getDefault(LocationManager.class).replaceLoad(type, oldLoad, newLoad); 420 } 421 422 boolean showQuanity = false; 423 424 public void toggleShowQuanity() { 425 if (showQuanity) { 426 showQuanity = false; 427 } else { 428 showQuanity = true; 429 } 430 quanity.setVisible(showQuanity); 431 updateCarQuanity(); 432 } 433 434 private void updateCarQuanity() { 435 if (!showQuanity) { 436 return; 437 } 438 int number = 0; 439 String item = (String) loadComboBox.getSelectedItem(); 440 for (Car car : InstanceManager.getDefault(CarManager.class).getList()) { 441 if (car.getLoadName().equals(item)) { 442 number++; 443 } 444 } 445 quanity.setText(Integer.toString(number)); 446 } 447 448 private void updateLoadComboBox() { 449 carLoads.updateComboBox(_type, loadComboBox); 450 loadComboBox.setSelectedItem(addTextBox.getText().trim()); 451 } 452 453 private void updateLoadType() { 454 String loadName = (String) loadComboBox.getSelectedItem(); 455 loadTypeComboBox.setSelectedItem(carLoads.getLoadType(_type, loadName)); 456 if (loadName != null && 457 (loadName.equals(InstanceManager.getDefault(CarLoads.class).getDefaultEmptyName()) || 458 loadName.equals(InstanceManager.getDefault(CarLoads.class) 459 .getDefaultLoadName()))) { 460 loadTypeComboBox.setEnabled(false); 461 } else { 462 loadTypeComboBox.setEnabled(true); 463 } 464 } 465 466 private void updatePriority() { 467 priorityComboBox.setSelectedItem(carLoads.getPriority(_type, (String) loadComboBox.getSelectedItem())); 468 } 469 470 private void updateHazardous() { 471 hazardousComboBox.setSelectedItem(carLoads.isHazardous(_type, (String) loadComboBox.getSelectedItem()) 472 ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo")); 473 } 474 475 private void updateCarCommentFields() { 476 pickupCommentTextField.setText(carLoads.getPickupComment(_type, (String) loadComboBox.getSelectedItem())); 477 dropCommentTextField.setText(carLoads.getDropComment(_type, (String) loadComboBox.getSelectedItem())); 478 } 479 480 private void enableButtons() { 481 addButton.setEnabled(_type != null); 482 deleteButton.setEnabled(_type != null); 483 replaceButton.setEnabled(_type != null); 484 saveButton.setEnabled(_type != null); 485 } 486 487 @Override 488 public void dispose() { 489 carLoads.removePropertyChangeListener(this); 490 super.dispose(); 491 } 492 493 @Override 494 public void propertyChange(java.beans.PropertyChangeEvent e) { 495 if (Control.SHOW_PROPERTY) { 496 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 497 .getNewValue()); 498 } 499 if (e.getPropertyName().equals(CarLoads.LOAD_CHANGED_PROPERTY)) { 500 updateLoadComboBox(); 501 } 502 } 503 504 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarLoadEditFrame.class); 505}