001package jmri.jmrit.operations.setup.gui; 002 003import java.awt.GridBagLayout; 004import java.beans.PropertyChangeListener; 005import java.io.IOException; 006import java.util.List; 007 008import javax.swing.*; 009 010import jmri.InstanceManager; 011import jmri.jmrit.display.LocoIcon; 012import jmri.jmrit.operations.OperationsXml; 013import jmri.jmrit.operations.rollingstock.cars.CarTypes; 014import jmri.jmrit.operations.routes.*; 015import jmri.jmrit.operations.setup.OperationsSetupXml; 016import jmri.jmrit.operations.setup.Setup; 017import jmri.jmrit.operations.setup.backup.*; 018import jmri.util.swing.*; 019import jmri.web.server.WebServerPreferences; 020 021/** 022 * Frame for user edit of operation parameters 023 * 024 * @author Dan Boudreau Copyright (C) 2008, 2010, 2011, 2012, 2025 025 */ 026public class OperationsSettingsPanel extends OperationsPreferencesPanel implements PropertyChangeListener { 027 028 // labels 029 private final JLabel textIconNorth = new JLabel(Bundle.getMessage("IconNorth")); 030 private final JLabel textIconSouth = new JLabel(Bundle.getMessage("IconSouth")); 031 private final JLabel textIconEast = new JLabel(Bundle.getMessage("IconEast")); 032 private final JLabel textIconWest = new JLabel(Bundle.getMessage("IconWest")); 033 private final JLabel textIconLocal = new JLabel(Bundle.getMessage("IconLocal")); 034 private final JLabel textIconTerminate = new JLabel(Bundle.getMessage("IconTerminate")); 035 036 // major buttons 037 private final JButton backupButton = new JButton(Bundle.getMessage("Backup")); 038 private final JButton restoreButton = new JButton(Bundle.getMessage("Restore")); 039 private final JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 040 041 // radio buttons 042 private final JRadioButton scaleZ = new JRadioButton("Z"); // NOI18N 043 private final JRadioButton scaleN = new JRadioButton("N"); // NOI18N 044 private final JRadioButton scaleTT = new JRadioButton("TT"); // NOI18N 045 private final JRadioButton scaleHOn3 = new JRadioButton("HOn3"); // NOI18N 046 private final JRadioButton scaleOO = new JRadioButton("OO"); // NOI18N 047 private final JRadioButton scaleHO = new JRadioButton("HO"); // NOI18N 048 private final JRadioButton scaleSn3 = new JRadioButton("Sn3"); // NOI18N 049 private final JRadioButton scaleS = new JRadioButton("S"); // NOI18N 050 private final JRadioButton scaleOn3 = new JRadioButton("On3"); // NOI18N 051 private final JRadioButton scaleO = new JRadioButton("O"); // NOI18N 052 private final JRadioButton scaleG1 = new JRadioButton("Gauge 1"); // NOI18N 053 private final JRadioButton scaleG_24 = new JRadioButton("G 1/24"); // NOI18N 054 055 private final JRadioButton typeDesc = new JRadioButton(Bundle.getMessage("Descriptive")); 056 private final JRadioButton typeAAR = new JRadioButton(Bundle.getMessage("AAR")); 057 058 private final JRadioButton feetUnit = new JRadioButton(Bundle.getMessage("Feet")); 059 private final JRadioButton meterUnit = new JRadioButton(Bundle.getMessage("Meter")); 060 061 // check boxes 062 final JCheckBox eastCheckBox = new JCheckBox(Bundle.getMessage("eastwest")); 063 final JCheckBox northCheckBox = new JCheckBox(Bundle.getMessage("northsouth")); 064 private final JCheckBox mainMenuCheckBox = new JCheckBox(Bundle.getMessage("MainMenu")); 065 private final JCheckBox closeOnSaveCheckBox = new JCheckBox(Bundle.getMessage("CloseOnSave")); 066 private final JCheckBox autoSaveCheckBox = new JCheckBox(Bundle.getMessage("AutoSave")); 067 private final JCheckBox autoBackupCheckBox = new JCheckBox(Bundle.getMessage("AutoBackup")); 068 private final JCheckBox iconCheckBox = new JCheckBox(Bundle.getMessage("trainIcon")); 069 private final JCheckBox appendCheckBox = new JCheckBox(Bundle.getMessage("trainIconAppend")); 070 071 // text field 072 JTextField panelTextField = new JTextField(30); 073 JTextField railroadNameTextField = new JTextField(35); 074 JTextField maxLengthTextField = new JTextField(5); 075 JTextField maxEngineSizeTextField = new JTextField(3); 076 JTextField hptTextField = new JTextField(3); 077 JTextField switchTimeTextField = new JTextField(3); 078 JTextField travelTimeTextField = new JTextField(3); 079 JTextField yearTextField = new JTextField(4); 080 081 // combo boxes 082 private final JComboBox<String> northComboBox = new JComboBox<>(); 083 private final JComboBox<String> southComboBox = new JComboBox<>(); 084 private final JComboBox<String> eastComboBox = new JComboBox<>(); 085 private final JComboBox<String> westComboBox = new JComboBox<>(); 086 private final JComboBox<String> localComboBox = new JComboBox<>(); 087 private final JComboBox<String> terminateComboBox = new JComboBox<>(); 088 089 // text area 090 private final JTextArea commentTextArea = new JTextArea(2, 80); 091 092 public OperationsSettingsPanel() { 093 super(); 094 095 // the following code sets the frame's initial state 096 // create manager to load operation settings 097 InstanceManager.getDefault(OperationsSetupXml.class); 098 099 // load fields 100 maxLengthTextField.setText(Integer.toString(Setup.getMaxTrainLength())); 101 maxEngineSizeTextField.setText(Integer.toString(Setup.getMaxNumberEngines())); 102 hptTextField.setText(Double.toString(Setup.getHorsePowerPerTon())); 103 switchTimeTextField.setText(Integer.toString(Setup.getSwitchTime())); 104 travelTimeTextField.setText(Integer.toString(Setup.getTravelTime())); 105 panelTextField.setText(Setup.getPanelName()); 106 yearTextField.setText(Setup.getYearModeled()); 107 commentTextArea.setText(Setup.getComment()); 108 109 // load checkboxes 110 mainMenuCheckBox.setSelected(Setup.isMainMenuEnabled()); 111 closeOnSaveCheckBox.setSelected(Setup.isCloseWindowOnSaveEnabled()); 112 autoSaveCheckBox.setSelected(Setup.isAutoSaveEnabled()); 113 autoBackupCheckBox.setSelected(Setup.isAutoBackupEnabled()); 114 iconCheckBox.setSelected(Setup.isTrainIconCordEnabled()); 115 appendCheckBox.setSelected(Setup.isTrainIconAppendEnabled()); 116 117 // add tool tips 118 backupButton.setToolTipText(Bundle.getMessage("BackupToolTip")); 119 restoreButton.setToolTipText(Bundle.getMessage("RestoreToolTip")); 120 saveButton.setToolTipText(Bundle.getMessage("SaveToolTip")); 121 panelTextField.setToolTipText(Bundle.getMessage("EnterPanelName")); 122 yearTextField.setToolTipText(Bundle.getMessage("EnterYearModeled")); 123 autoSaveCheckBox.setToolTipText(Bundle.getMessage("AutoSaveTip")); 124 autoBackupCheckBox.setToolTipText(Bundle.getMessage("AutoBackUpTip")); 125 maxLengthTextField.setToolTipText(Bundle.getMessage("MaxLengthTip")); 126 maxEngineSizeTextField.setToolTipText(Bundle.getMessage("MaxEngineTip")); 127 hptTextField.setToolTipText(Bundle.getMessage("HPperTonTip")); 128 switchTimeTextField.setToolTipText(Bundle.getMessage("SwitchTimeTip")); 129 travelTimeTextField.setToolTipText(Bundle.getMessage("TravelTimeTip")); 130 railroadNameTextField.setToolTipText(Bundle.getMessage("RailroadNameTip")); 131 commentTextArea.setToolTipText(Bundle.getMessage("CommentTip")); 132 133 // Layout the panel by rows 134 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 135 JPanel panel = new JPanel(); 136 JScrollPane panelPane = new JScrollPane(panel); 137 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 138 panelPane.setBorder(BorderFactory.createTitledBorder("")); 139 140 // row 1a 141 JPanel p1 = new JPanel(); 142 p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 143 144 JPanel pRailroadName = new JPanel(); 145 pRailroadName.setLayout(new GridBagLayout()); 146 pRailroadName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RailroadName"))); 147 addItem(pRailroadName, railroadNameTextField, 0, 0); 148 p1.add(pRailroadName); 149 150 // row 1b 151 JPanel pTrainDir = new JPanel(); 152 pTrainDir.setLayout(new GridBagLayout()); 153 pTrainDir.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("direction"))); 154 addItemLeft(pTrainDir, northCheckBox, 1, 2); 155 addItemLeft(pTrainDir, eastCheckBox, 2, 2); 156 p1.add(pTrainDir); 157 158 setDirectionCheckBox(Setup.getTrainDirection()); 159 160 // row 3a 161 JPanel p3 = new JPanel(); 162 p3.setLayout(new BoxLayout(p3, BoxLayout.X_AXIS)); 163 164 JPanel pTrainLength = new JPanel(); 165 pTrainLength.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("MaxLength"))); 166 addItem(pTrainLength, maxLengthTextField, 0, 0); 167 p3.add(pTrainLength); 168 169 // row 3b 170 JPanel pMaxEngine = new JPanel(); 171 pMaxEngine.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("MaxEngine"))); 172 addItem(pMaxEngine, maxEngineSizeTextField, 0, 0); 173 p3.add(pMaxEngine); 174 175 // row 3c 176 JPanel pHPT = new JPanel(); 177 pHPT.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("HPT"))); 178 addItem(pHPT, hptTextField, 0, 0); 179 p3.add(pHPT); 180 181 JPanel pSwitchTime = new JPanel(); 182 pSwitchTime.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("MoveTime"))); 183 addItem(pSwitchTime, switchTimeTextField, 0, 0); 184 p3.add(pSwitchTime); 185 186 // row 3d 187 JPanel pTravelTime = new JPanel(); 188 pTravelTime.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TravelTime"))); 189 addItem(pTravelTime, travelTimeTextField, 0, 0); 190 p3.add(pTravelTime); 191 192 // row 2 193 JPanel pScale = new JPanel(); 194 pScale.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Scale"))); 195 196 ButtonGroup scaleGroup = new ButtonGroup(); 197 scaleGroup.add(scaleZ); 198 scaleGroup.add(scaleN); 199 scaleGroup.add(scaleTT); 200 scaleGroup.add(scaleHOn3); 201 scaleGroup.add(scaleHO); 202 scaleGroup.add(scaleOO); 203 scaleGroup.add(scaleSn3); 204 scaleGroup.add(scaleS); 205 scaleGroup.add(scaleOn3); 206 scaleGroup.add(scaleO); 207 scaleGroup.add(scaleG1); 208 scaleGroup.add(scaleG_24); 209 210 scaleZ.setToolTipText(Bundle.getMessage("Ratio") + Setup.Z_RATIO); 211 scaleN.setToolTipText(Bundle.getMessage("Ratio") + Setup.N_RATIO); 212 scaleTT.setToolTipText(Bundle.getMessage("Ratio") + Setup.TT_RATIO); 213 scaleHOn3.setToolTipText(Bundle.getMessage("Ratio") + Setup.HO_RATIO); 214 scaleHO.setToolTipText(Bundle.getMessage("Ratio") + Setup.HO_RATIO); 215 scaleOO.setToolTipText(Bundle.getMessage("Ratio") + Setup.OO_RATIO); 216 scaleSn3.setToolTipText(Bundle.getMessage("Ratio") + Setup.S_RATIO); 217 scaleS.setToolTipText(Bundle.getMessage("Ratio") + Setup.S_RATIO); 218 scaleOn3.setToolTipText(Bundle.getMessage("Ratio") + Setup.O_RATIO); 219 scaleO.setToolTipText(Bundle.getMessage("Ratio") + Setup.O_RATIO); 220 scaleG1.setToolTipText(Bundle.getMessage("Ratio") + Setup.Gauge1_RATIO); 221 scaleG_24.setToolTipText(Bundle.getMessage("Ratio") + Setup.G_24_RATIO); 222 223 pScale.add(scaleZ); 224 pScale.add(scaleN); 225 pScale.add(scaleTT); 226 pScale.add(scaleHOn3); 227 pScale.add(scaleHO); 228 pScale.add(scaleOO); 229 pScale.add(scaleSn3); 230 pScale.add(scaleS); 231 pScale.add(scaleOn3); 232 pScale.add(scaleO); 233 pScale.add(scaleG1); 234 pScale.add(scaleG_24); 235 setScale(); 236 237 // row 4a 238 JPanel p9 = new JPanel(); 239 p9.setLayout(new BoxLayout(p9, BoxLayout.X_AXIS)); 240 241 JPanel pCarTypeButtons = new JPanel(); 242 pCarTypeButtons.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("CarTypes"))); 243 ButtonGroup carTypeGroup = new ButtonGroup(); 244 carTypeGroup.add(typeDesc); 245 carTypeGroup.add(typeAAR); 246 pCarTypeButtons.add(typeDesc); 247 pCarTypeButtons.add(typeAAR); 248 p9.add(pCarTypeButtons); 249 setCarTypes(); 250 251 // row 4b 252 JPanel pLengthUnit = new JPanel(); 253 pLengthUnit.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLength"))); 254 ButtonGroup lengthUnitGroup = new ButtonGroup(); 255 lengthUnitGroup.add(feetUnit); 256 lengthUnitGroup.add(meterUnit); 257 pLengthUnit.add(feetUnit); 258 pLengthUnit.add(meterUnit); 259 p9.add(pLengthUnit); 260 setLengthUnit(); 261 262 // row 4c 263 JPanel pYearModeled = new JPanel(); 264 pYearModeled.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutYearModeled"))); 265 pYearModeled.add(yearTextField); 266 267 p9.add(pYearModeled); 268 269 // Option panel 270 JPanel options = new JPanel(); 271 options.setLayout(new GridBagLayout()); 272 options.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptions"))); 273 addItem(options, mainMenuCheckBox, 0, 0); 274 addItem(options, closeOnSaveCheckBox, 1, 0); 275 addItem(options, autoSaveCheckBox, 2, 0); 276 addItem(options, autoBackupCheckBox, 3, 0); 277 278 // p9.add(options); 279 // 1st scroll panel 280 panel.add(p1); 281 panel.add(pScale); 282 panel.add(p3); 283 panel.add(p9); 284 285 // Icon panel 286 JPanel pIcon = new JPanel(); 287 pIcon.setLayout(new BoxLayout(pIcon, BoxLayout.Y_AXIS)); 288 JScrollPane pIconPane = new JScrollPane(pIcon); 289 pIconPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPanelOptions"))); 290 291 // row 1 Icon panel 292 JPanel p1Icon = new JPanel(); 293 p1Icon.setLayout(new BoxLayout(p1Icon, BoxLayout.X_AXIS)); 294 295 JPanel pPanelName = new JPanel(); 296 pPanelName.setLayout(new GridBagLayout()); 297 pPanelName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPanelName"))); 298 addItem(pPanelName, panelTextField, 0, 0); 299 p1Icon.add(pPanelName); 300 301 JPanel pIconControl = new JPanel(); 302 pIconControl.setLayout(new GridBagLayout()); 303 pIconControl.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutIconOptions"))); 304 addItem(pIconControl, appendCheckBox, 0, 0); 305 addItem(pIconControl, iconCheckBox, 1, 0); 306 p1Icon.add(pIconControl); 307 308 pIcon.add(p1Icon); 309 310 JPanel pIconColors = new JPanel(); 311 pIconColors.setLayout(new GridBagLayout()); 312 pIconColors.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutIconColors"))); 313 314 textIconNorth.setLabelFor(northComboBox); 315 addItem(pIconColors, textIconNorth, 0, 4); 316 addItemLeft(pIconColors, northComboBox, 1, 4); 317 textIconSouth.setLabelFor(southComboBox); 318 addItem(pIconColors, textIconSouth, 0, 5); 319 addItemLeft(pIconColors, southComboBox, 1, 5); 320 textIconEast.setLabelFor(eastComboBox); 321 addItem(pIconColors, textIconEast, 0, 8); 322 addItemLeft(pIconColors, eastComboBox, 1, 8); 323 textIconWest.setLabelFor(westComboBox); 324 addItem(pIconColors, textIconWest, 0, 9); 325 addItemLeft(pIconColors, westComboBox, 1, 9); 326 textIconLocal.setLabelFor(localComboBox); 327 addItem(pIconColors, textIconLocal, 0, 10); 328 addItemLeft(pIconColors, localComboBox, 1, 10); 329 textIconTerminate.setLabelFor(terminateComboBox); 330 addItem(pIconColors, textIconTerminate, 0, 11); 331 addItemLeft(pIconColors, terminateComboBox, 1, 11); 332 333 pIcon.add(pIconColors); 334 335 loadIconComboBox(northComboBox); 336 loadIconComboBox(southComboBox); 337 loadIconComboBox(eastComboBox); 338 loadIconComboBox(westComboBox); 339 loadIconComboBox(localComboBox); 340 loadIconComboBox(terminateComboBox); 341 northComboBox.setSelectedItem(Setup.getTrainIconColorNorth()); 342 southComboBox.setSelectedItem(Setup.getTrainIconColorSouth()); 343 eastComboBox.setSelectedItem(Setup.getTrainIconColorEast()); 344 westComboBox.setSelectedItem(Setup.getTrainIconColorWest()); 345 localComboBox.setSelectedItem(Setup.getTrainIconColorLocal()); 346 terminateComboBox.setSelectedItem(Setup.getTrainIconColorTerminate()); 347 348 // comment 349 JPanel pC = new JPanel(); 350 pC.setLayout(new GridBagLayout()); 351 pC.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Comment"))); 352 JScrollPane commentScroller = new JScrollPane(commentTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 353 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 354 addItem(pC, commentScroller, 0, 0); 355 356 pIcon.add(pC); 357 358 // row 15 359 JPanel pControl = new JPanel(); 360 pControl.setLayout(new GridBagLayout()); 361 addItem(pControl, restoreButton, 0, 9); 362 addItem(pControl, backupButton, 1, 9); 363 addItem(pControl, saveButton, 3, 9); 364 365 add(panelPane); 366 add(options); 367 add(pIconPane); 368 add(pControl); 369 370 // set up buttons 371 addButtonAction(backupButton); 372 addButtonAction(restoreButton); 373 addButtonAction(saveButton); 374 addCheckBoxAction(eastCheckBox); 375 addCheckBoxAction(northCheckBox); 376 377 // now provide the railroad name 378 railroadNameTextField.setText(Setup.getRailroadName()); 379 } 380 381 // Save, Delete, Add buttons 382 @Override 383 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 384 if (ae.getSource() == backupButton) { 385 // Backup and Restore dialogs are now modal. so no need to check for an existing 386 // instance 387 BackupDialog bd = new BackupDialog(); 388 bd.pack(); 389 bd.setLocationRelativeTo(null); 390 bd.setVisible(true); 391 } 392 if (ae.getSource() == restoreButton) { 393 RestoreDialog rd = new RestoreDialog(); 394 rd.pack(); 395 rd.setLocationRelativeTo(null); 396 rd.setVisible(true); 397 } 398 if (ae.getSource() == saveButton) { 399 save(); 400 } 401 } 402 403 private void save() { 404 // check input fields 405 int maxTrainLength; 406 try { 407 maxTrainLength = Integer.parseInt(maxLengthTextField.getText()); 408 } catch (NumberFormatException e) { 409 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MaxLength"), Bundle.getMessage("CanNotAcceptNumber"), 410 JmriJOptionPane.ERROR_MESSAGE); 411 return; 412 } 413 // warn about train length being too short 414 if (maxTrainLength != Setup.getMaxTrainLength()) { 415 if (maxTrainLength < 500 && Setup.getLengthUnit().equals(Setup.FEET) || 416 maxTrainLength < 160 && Setup.getLengthUnit().equals(Setup.METER)) { 417 JmriJOptionPane.showMessageDialog(this, 418 Bundle.getMessage("LimitTrainLength", 419 maxTrainLength, Setup.getLengthUnit().toLowerCase()), 420 Bundle.getMessage("WarningTooShort"), JmriJOptionPane.WARNING_MESSAGE); 421 } 422 } 423 424 try { 425 Integer.parseInt(maxEngineSizeTextField.getText()); 426 } catch (NumberFormatException e) { 427 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MaxEngine"), Bundle.getMessage("CanNotAcceptNumber"), 428 JmriJOptionPane.ERROR_MESSAGE); 429 return; 430 } 431 432 try { 433 Double.parseDouble(hptTextField.getText()); 434 } catch (NumberFormatException e) { 435 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("HPT"), Bundle.getMessage("CanNotAcceptNumber"), 436 JmriJOptionPane.ERROR_MESSAGE); 437 return; 438 } 439 440 try { 441 Integer.parseInt(switchTimeTextField.getText()); 442 } catch (NumberFormatException e) { 443 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MoveTime"), Bundle.getMessage("CanNotAcceptNumber"), 444 JmriJOptionPane.ERROR_MESSAGE); 445 return; 446 } 447 448 try { 449 Integer.parseInt(travelTimeTextField.getText()); 450 } catch (NumberFormatException e) { 451 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("TravelTime"), 452 Bundle.getMessage("CanNotAcceptNumber"), JmriJOptionPane.ERROR_MESSAGE); 453 return; 454 } 455 456 try { 457 if (!yearTextField.getText().trim().isEmpty()) { 458 Integer.parseInt(yearTextField.getText().trim()); 459 } 460 } catch (NumberFormatException e) { 461 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("BorderLayoutYearModeled"), 462 Bundle.getMessage("CanNotAcceptNumber"), JmriJOptionPane.ERROR_MESSAGE); 463 return; 464 } 465 466 // if max train length has changed, check routes 467 checkRoutes(); 468 469 // set car types 470 if (typeDesc.isSelected() && !Setup.getCarTypes().equals(Setup.DESCRIPTIVE) || 471 typeAAR.isSelected() && !Setup.getCarTypes().equals(Setup.AAR)) { 472 473 // backup files before changing car type descriptions 474 AutoBackup backup = new AutoBackup(); 475 try { 476 backup.autoBackup(); 477 } catch (IOException ex) { 478 UnexpectedExceptionContext context = new UnexpectedExceptionContext(ex, 479 "Auto backup before changing Car types"); // NOI18N 480 ExceptionDisplayFrame.displayExceptionDisplayFrame(this, context); 481 } 482 483 if (typeDesc.isSelected()) { 484 InstanceManager.getDefault(CarTypes.class).changeDefaultNames(Setup.DESCRIPTIVE); 485 Setup.setCarTypes(Setup.DESCRIPTIVE); 486 } else { 487 InstanceManager.getDefault(CarTypes.class).changeDefaultNames(Setup.AAR); 488 Setup.setCarTypes(Setup.AAR); 489 } 490 491 // save all the modified files 492 OperationsXml.save(); 493 } 494 // main menu enabled? 495 Setup.setMainMenuEnabled(mainMenuCheckBox.isSelected()); 496 Setup.setCloseWindowOnSaveEnabled(closeOnSaveCheckBox.isSelected()); 497 Setup.setAutoSaveEnabled(autoSaveCheckBox.isSelected()); 498 Setup.setAutoBackupEnabled(autoBackupCheckBox.isSelected()); 499 500 // add panel name to setup 501 Setup.setPanelName(panelTextField.getText()); 502 503 // train Icon X&Y 504 Setup.setTrainIconCordEnabled(iconCheckBox.isSelected()); 505 Setup.setTrainIconAppendEnabled(appendCheckBox.isSelected()); 506 507 // save train icon colors 508 Setup.setTrainIconColorNorth((String) northComboBox.getSelectedItem()); 509 Setup.setTrainIconColorSouth((String) southComboBox.getSelectedItem()); 510 Setup.setTrainIconColorEast((String) eastComboBox.getSelectedItem()); 511 Setup.setTrainIconColorWest((String) westComboBox.getSelectedItem()); 512 Setup.setTrainIconColorLocal((String) localComboBox.getSelectedItem()); 513 Setup.setTrainIconColorTerminate((String) terminateComboBox.getSelectedItem()); 514 // set train direction 515 int direction = 0; 516 if (eastCheckBox.isSelected()) { 517 direction = Setup.EAST + Setup.WEST; 518 } 519 if (northCheckBox.isSelected()) { 520 direction += Setup.NORTH + Setup.SOUTH; 521 } 522 Setup.setTrainDirection(direction); 523 Setup.setMaxNumberEngines(Integer.parseInt(maxEngineSizeTextField.getText())); 524 Setup.setHorsePowerPerTon(Double.parseDouble(hptTextField.getText())); 525 // set switch time 526 Setup.setSwitchTime(Integer.parseInt(switchTimeTextField.getText())); 527 // set travel time 528 Setup.setTravelTime(Integer.parseInt(travelTimeTextField.getText())); 529 // set scale 530 Setup.setScale(getSelectedScale()); 531 532 if (!railroadNameTextField.getText() 533 .equals(InstanceManager.getDefault(WebServerPreferences.class).getRailroadName())) { 534 Setup.setRailroadName(railroadNameTextField.getText()); 535 int results = JmriJOptionPane.showConfirmDialog(this, 536 Bundle.getMessage("ChangeRailroadName", 537 InstanceManager.getDefault(WebServerPreferences.class).getRailroadName(), 538 Setup.getRailroadName()), 539 Bundle.getMessage("ChangeJMRIRailroadName"), JmriJOptionPane.YES_NO_OPTION); 540 if (results == JmriJOptionPane.YES_OPTION) { 541 InstanceManager.getDefault(WebServerPreferences.class).setRailroadName(Setup.getRailroadName()); 542 InstanceManager.getDefault(WebServerPreferences.class).save(); 543 } 544 } 545 // Set Unit of Length 546 if (feetUnit.isSelected()) { 547 Setup.setLengthUnit(Setup.FEET); 548 } 549 if (meterUnit.isSelected()) { 550 Setup.setLengthUnit(Setup.METER); 551 } 552 Setup.setYearModeled(yearTextField.getText().trim()); 553 // set max train length 554 Setup.setMaxTrainLength(Integer.parseInt(maxLengthTextField.getText())); 555 Setup.setComment(commentTextArea.getText()); 556 557 InstanceManager.getDefault(OperationsSetupXml.class).writeOperationsFile(); 558 var topLevelAncestor = getTopLevelAncestor(); 559 if (Setup.isCloseWindowOnSaveEnabled() && topLevelAncestor instanceof OperationsSettingsFrame) { 560 ((OperationsSettingsFrame) topLevelAncestor).dispose(); 561 } 562 } 563 564 // if max train length has changed, check routes 565 private void checkRoutes() { 566 int maxLength = Integer.parseInt(maxLengthTextField.getText()); 567 if (maxLength > Setup.getMaxTrainLength()) { 568 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("RouteLengthNotModified"), 569 Bundle.getMessage("MaxTrainLengthIncreased", 570 maxLength, Setup.getLengthUnit().toLowerCase()), 571 JmriJOptionPane.INFORMATION_MESSAGE); 572 } 573 if (maxLength < Setup.getMaxTrainLength()) { 574 StringBuilder sb = new StringBuilder(); 575 List<Route> routes = InstanceManager.getDefault(RouteManager.class).getRoutesByNameList(); 576 int count = 0; 577 for (Route route : routes) { 578 for (RouteLocation rl : route.getLocationsBySequenceList()) { 579 if (rl.getMaxTrainLength() > maxLength) { 580 String s = Bundle.getMessage("RouteMaxLengthExceeds", 581 route.getName(), rl.getName(), rl.getMaxTrainLength(), maxLength); 582 log.info(s); 583 sb.append(s).append(NEW_LINE); 584 count++; 585 break; 586 } 587 } 588 // maximum of 20 route warnings 589 if (count > 20) { 590 sb.append(Bundle.getMessage("More")).append(NEW_LINE); 591 break; 592 } 593 } 594 if (sb.length() > 0) { 595 JmriJOptionPane.showMessageDialog(this, sb.toString(), Bundle.getMessage("YouNeedToAdjustRoutes"), 596 JmriJOptionPane.WARNING_MESSAGE); 597 if (JmriJOptionPane.showConfirmDialog(this, 598 Bundle.getMessage("ChangeMaximumTrainDepartureLength", 599 maxLength), 600 Bundle.getMessage("ModifyAllRoutes"), JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) { 601 routes.stream().forEach((route) -> { 602 route.getLocationsBySequenceList().stream().filter((rl) -> (rl.getMaxTrainLength() > maxLength)) 603 .map((rl) -> { 604 log.debug("Setting route ({}) routeLocation ({}) max traim length to {}", 605 route.getName(), rl.getName(), maxLength); // NOI18N 606 return rl; 607 }).forEach((rl) -> { 608 rl.setMaxTrainLength(maxLength); 609 }); 610 }); 611 // save the route changes 612 InstanceManager.getDefault(RouteManagerXml.class).writeOperationsFile(); 613 } 614 } 615 } 616 } 617 618 @Override 619 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 620 if (ae.getSource() == northCheckBox) { 621 if (!northCheckBox.isSelected()) { 622 eastCheckBox.setSelected(true); 623 } 624 } 625 if (ae.getSource() == eastCheckBox) { 626 if (!eastCheckBox.isSelected()) { 627 northCheckBox.setSelected(true); 628 } 629 } 630 int direction = 0; 631 if (eastCheckBox.isSelected()) { 632 direction += Setup.EAST; 633 } 634 if (northCheckBox.isSelected()) { 635 direction += Setup.NORTH; 636 } 637 setDirectionCheckBox(direction); 638 } 639 640 private void setScale() { 641 switch (Setup.getScale()) { 642 case Setup.Z_SCALE: 643 scaleZ.setSelected(true); 644 break; 645 case Setup.N_SCALE: 646 scaleN.setSelected(true); 647 break; 648 case Setup.TT_SCALE: 649 scaleTT.setSelected(true); 650 break; 651 case Setup.HOn3_SCALE: 652 scaleHOn3.setSelected(true); 653 break; 654 case Setup.HO_SCALE: 655 scaleHO.setSelected(true); 656 break; 657 case Setup.OO_SCALE: 658 scaleOO.setSelected(true); 659 break; 660 case Setup.Sn3_SCALE: 661 scaleSn3.setSelected(true); 662 break; 663 case Setup.S_SCALE: 664 scaleS.setSelected(true); 665 break; 666 case Setup.On3_SCALE: 667 scaleOn3.setSelected(true); 668 break; 669 case Setup.O_SCALE: 670 scaleO.setSelected(true); 671 break; 672 case Setup.Gauge1_SCALE: 673 scaleG1.setSelected(true); 674 break; 675 case Setup.G_24_SCALE: 676 scaleG_24.setSelected(true); 677 break; 678 default: 679 log.error("Unknown scale"); 680 } 681 } 682 683 private int getSelectedScale() { 684 int scale = 0; 685 if (scaleZ.isSelected()) { 686 scale = Setup.Z_SCALE; 687 } 688 if (scaleN.isSelected()) { 689 scale = Setup.N_SCALE; 690 } 691 if (scaleTT.isSelected()) { 692 scale = Setup.TT_SCALE; 693 } 694 if (scaleOO.isSelected()) { 695 scale = Setup.OO_SCALE; 696 } 697 if (scaleHOn3.isSelected()) { 698 scale = Setup.HOn3_SCALE; 699 } 700 if (scaleHO.isSelected()) { 701 scale = Setup.HO_SCALE; 702 } 703 if (scaleSn3.isSelected()) { 704 scale = Setup.Sn3_SCALE; 705 } 706 if (scaleS.isSelected()) { 707 scale = Setup.S_SCALE; 708 } 709 if (scaleOn3.isSelected()) { 710 scale = Setup.On3_SCALE; 711 } 712 if (scaleO.isSelected()) { 713 scale = Setup.O_SCALE; 714 } 715 if (scaleG1.isSelected()) { 716 scale = Setup.Gauge1_SCALE; 717 } 718 if (scaleG_24.isSelected()) { 719 scale = Setup.G_24_SCALE; 720 } 721 return scale; 722 } 723 724 private void setCarTypes() { 725 typeDesc.setSelected(Setup.getCarTypes().equals(Setup.DESCRIPTIVE)); 726 typeAAR.setSelected(Setup.getCarTypes().equals(Setup.AAR)); 727 } 728 729 private void setDirectionCheckBox(int direction) { 730 eastCheckBox.setSelected((direction & Setup.EAST) == Setup.EAST); 731 textIconEast.setVisible((direction & Setup.EAST) == Setup.EAST); 732 eastComboBox.setVisible((direction & Setup.EAST) == Setup.EAST); 733 textIconWest.setVisible((direction & Setup.EAST) == Setup.EAST); 734 westComboBox.setVisible((direction & Setup.EAST) == Setup.EAST); 735 northCheckBox.setSelected((direction & Setup.NORTH) == Setup.NORTH); 736 textIconNorth.setVisible((direction & Setup.NORTH) == Setup.NORTH); 737 northComboBox.setVisible((direction & Setup.NORTH) == Setup.NORTH); 738 textIconSouth.setVisible((direction & Setup.NORTH) == Setup.NORTH); 739 southComboBox.setVisible((direction & Setup.NORTH) == Setup.NORTH); 740 } 741 742 private void setLengthUnit() { 743 feetUnit.setSelected(Setup.getLengthUnit().equals(Setup.FEET)); 744 meterUnit.setSelected(Setup.getLengthUnit().equals(Setup.METER)); 745 } 746 747 private void loadIconComboBox(JComboBox<String> comboBox) { 748 for (String color : LocoIcon.getLocoColors()) { 749 comboBox.addItem(color); 750 } 751 } 752 753 @Override 754 public void propertyChange(java.beans.PropertyChangeEvent e) { 755 log.debug("propertyChange ({}), new: ({})", e.getPropertyName(), e.getNewValue()); 756 } 757 758 @Override 759 public String getTabbedPreferencesTitle() { 760 return Bundle.getMessage("TitleOperationsSetup"); 761 } 762 763 @Override 764 public String getPreferencesTooltip() { 765 return null; 766 } 767 768 @Override 769 public void savePreferences() { 770 this.save(); 771 } 772 773 @Override 774 public boolean isDirty() { 775 if (// set car types 776 (typeDesc.isSelected() && !Setup.getCarTypes().equals(Setup.DESCRIPTIVE)) || 777 (typeAAR.isSelected() && !Setup.getCarTypes().equals(Setup.AAR)) 778 // main menu enabled? 779 || 780 Setup.isMainMenuEnabled() != mainMenuCheckBox.isSelected() || 781 Setup.isCloseWindowOnSaveEnabled() != closeOnSaveCheckBox.isSelected() || 782 Setup.isAutoSaveEnabled() != autoSaveCheckBox.isSelected() || 783 Setup.isAutoBackupEnabled() != autoBackupCheckBox.isSelected() 784 // add panel name to setup 785 || 786 !Setup.getPanelName().equals(panelTextField.getText()) 787 // train Icon X&Y 788 || 789 Setup.isTrainIconCordEnabled() != iconCheckBox.isSelected() || 790 Setup.isTrainIconAppendEnabled() != appendCheckBox.isSelected() 791 // train Icon X&Y 792 || 793 Setup.isTrainIconCordEnabled() != iconCheckBox.isSelected() || 794 Setup.isTrainIconAppendEnabled() != appendCheckBox.isSelected() 795 // save train icon colors 796 || 797 !Setup.getTrainIconColorNorth().equals(northComboBox.getSelectedItem()) || 798 !Setup.getTrainIconColorSouth().equals(southComboBox.getSelectedItem()) || 799 !Setup.getTrainIconColorEast().equals(eastComboBox.getSelectedItem()) || 800 !Setup.getTrainIconColorWest().equals(westComboBox.getSelectedItem()) || 801 !Setup.getTrainIconColorLocal().equals(localComboBox.getSelectedItem()) || 802 !Setup.getTrainIconColorTerminate().equals(terminateComboBox.getSelectedItem()) || 803 Setup.getMaxNumberEngines() != Integer.parseInt(maxEngineSizeTextField.getText()) || 804 Setup.getHorsePowerPerTon() != Integer.parseInt(hptTextField.getText()) 805 // switch time 806 || 807 Setup.getSwitchTime() != Integer.parseInt(switchTimeTextField.getText()) 808 // travel time 809 || 810 Setup.getTravelTime() != Integer.parseInt(travelTimeTextField.getText()) || 811 !Setup.getYearModeled().equals(yearTextField.getText().trim()) || 812 Setup.getMaxTrainLength() != Integer.parseInt(maxLengthTextField.getText()) || 813 !Setup.getComment().equals(this.commentTextArea.getText())) { 814 return true; 815 } 816 817 // set train direction 818 int direction = 0; 819 if (eastCheckBox.isSelected()) { 820 direction = Setup.EAST + Setup.WEST; 821 } 822 if (northCheckBox.isSelected()) { 823 direction += Setup.NORTH + Setup.SOUTH; 824 } 825 // get scale 826 int scale = getSelectedScale(); 827 String lengthUnit = ""; 828 // Set Unit of Length 829 if (feetUnit.isSelected()) { 830 lengthUnit = Setup.FEET; 831 } 832 if (meterUnit.isSelected()) { 833 lengthUnit = Setup.METER; 834 } 835 return (Setup.getTrainDirection() != direction || 836 Setup.getScale() != scale || 837 !Setup.getRailroadName().equals(this.railroadNameTextField.getText()) || 838 !Setup.getLengthUnit().equals(lengthUnit)); 839 } 840 841 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OperationsSettingsPanel.class); 842 843}