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