001package jmri.jmrit.operations.setup.gui; 002 003import java.awt.GridBagLayout; 004 005import javax.swing.*; 006 007import jmri.InstanceManager; 008import jmri.jmrit.operations.OperationsXml; 009import jmri.jmrit.operations.locations.LocationManager; 010import jmri.jmrit.operations.locations.tools.LocationsByQuickServiceFrame; 011import jmri.jmrit.operations.setup.Setup; 012import jmri.jmrit.operations.trains.TrainManager; 013import jmri.util.swing.JmriJOptionPane; 014 015/** 016 * Frame for user edit of setup options 017 * 018 * @author Dan Boudreau Copyright (C) 2010, 2011, 2012, 2013, 2015, 2026 019 */ 020public class OptionPanel extends OperationsPreferencesPanel { 021 022 // labels 023 // major buttons 024 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 025 026 // radio buttons 027 JRadioButton buildNormal = new JRadioButton(Bundle.getMessage("Normal")); 028 JRadioButton buildAggressive = new JRadioButton(Bundle.getMessage("Aggressive")); 029 JRadioButton buildOnTime = new JRadioButton(Bundle.getMessage("OnTime")); 030 031 // check boxes 032 JCheckBox routerCheckBox = new JCheckBox(Bundle.getMessage("EnableCarRouting")); 033 JCheckBox routerYardCheckBox = new JCheckBox(Bundle.getMessage("EnableCarRoutingYard")); 034 JCheckBox routerStagingCheckBox = new JCheckBox(Bundle.getMessage("EnableCarRoutingStaging")); 035 JCheckBox routerAllTrainsBox = new JCheckBox(Bundle.getMessage("AllTrains")); 036 JCheckBox routerRestrictBox = new JCheckBox(Bundle.getMessage("EnableTrackDestinationRestrictions")); 037 038 JCheckBox valueCheckBox = new JCheckBox(Bundle.getMessage("EnableValue")); 039 JCheckBox rfidCheckBox = new JCheckBox(Bundle.getMessage("EnableRfid")); 040 JCheckBox carLoggerCheckBox = new JCheckBox(Bundle.getMessage("EnableCarLogging")); 041 JCheckBox engineLoggerCheckBox = new JCheckBox(Bundle.getMessage("EnableEngineLogging")); 042 JCheckBox trainLoggerCheckBox = new JCheckBox(Bundle.getMessage("EnableTrainLogging")); 043 044 JCheckBox localInterchangeCheckBox = new JCheckBox(Bundle.getMessage("AllowLocalInterchange")); 045 JCheckBox localSpurCheckBox = new JCheckBox(Bundle.getMessage("AllowLocalSpur")); 046 JCheckBox localYardCheckBox = new JCheckBox(Bundle.getMessage("AllowLocalYard")); 047 048 JCheckBox trainIntoStagingCheckBox = new JCheckBox(Bundle.getMessage("TrainIntoStaging")); 049 JCheckBox stagingAvailCheckBox = new JCheckBox(Bundle.getMessage("StagingAvailable")); 050 JCheckBox stagingTurnCheckBox = new JCheckBox(Bundle.getMessage("AllowCarsToReturn")); 051 JCheckBox promptFromTrackStagingCheckBox = new JCheckBox(Bundle.getMessage("PromptFromStaging")); 052 JCheckBox promptToTrackStagingCheckBox = new JCheckBox(Bundle.getMessage("PromptToStaging")); 053 JCheckBox tryNormalStagingCheckBox = new JCheckBox(Bundle.getMessage("TryNormalStaging")); 054 055 JCheckBox generateCvsManifestCheckBox = new JCheckBox(Bundle.getMessage("GenerateCsvManifest")); 056 JCheckBox generateCvsSwitchListCheckBox = new JCheckBox(Bundle.getMessage("GenerateCsvSwitchList")); 057 058 JCheckBox enableVsdCheckBox = new JCheckBox(Bundle.getMessage("EnableVSD")); 059 JCheckBox saveTrainManifestCheckBox = new JCheckBox(Bundle.getMessage("SaveManifests")); 060 061 // text field 062 JTextField dwellTimeTextField = new JTextField(10); 063 JTextField rfidTextField = new JTextField(10); 064 JTextField valueTextField = new JTextField(10); 065 066 // combo boxes 067 JComboBox<Integer> numberPassesComboBox = new JComboBox<>(); 068 069 public OptionPanel() { 070 071 // load checkboxes 072 localInterchangeCheckBox.setSelected(Setup.isLocalInterchangeMovesEnabled()); 073 localSpurCheckBox.setSelected(Setup.isLocalSpurMovesEnabled()); 074 localYardCheckBox.setSelected(Setup.isLocalYardMovesEnabled()); 075 // staging options 076 trainIntoStagingCheckBox.setSelected(Setup.isStagingTrainCheckEnabled()); 077 stagingAvailCheckBox.setSelected(Setup.isStagingTrackImmediatelyAvail()); 078 stagingTurnCheckBox.setSelected(Setup.isStagingAllowReturnEnabled()); 079 promptToTrackStagingCheckBox.setSelected(Setup.isStagingPromptToEnabled()); 080 promptFromTrackStagingCheckBox.setSelected(Setup.isStagingPromptFromEnabled()); 081 tryNormalStagingCheckBox.setSelected(Setup.isStagingTryNormalBuildEnabled()); 082 // router 083 routerCheckBox.setSelected(Setup.isCarRoutingEnabled()); 084 routerYardCheckBox.setSelected(Setup.isCarRoutingViaYardsEnabled()); 085 routerStagingCheckBox.setSelected(Setup.isCarRoutingViaStagingEnabled()); 086 routerAllTrainsBox.setSelected(!Setup.isOnlyActiveTrainsEnabled()); 087 routerRestrictBox.setSelected(Setup.isCheckCarDestinationEnabled()); 088 // logging options 089 carLoggerCheckBox.setSelected(Setup.isCarLoggerEnabled()); 090 engineLoggerCheckBox.setSelected(Setup.isEngineLoggerEnabled()); 091 trainLoggerCheckBox.setSelected(Setup.isTrainLoggerEnabled()); 092 // save manifests 093 saveTrainManifestCheckBox.setSelected(Setup.isSaveTrainManifestsEnabled()); 094 095 generateCvsManifestCheckBox.setSelected(Setup.isGenerateCsvManifestEnabled()); 096 generateCvsSwitchListCheckBox.setSelected(Setup.isGenerateCsvSwitchListEnabled()); 097 valueCheckBox.setSelected(Setup.isValueEnabled()); 098 rfidCheckBox.setSelected(Setup.isRfidEnabled()); 099 enableVsdCheckBox.setSelected(Setup.isVsdPhysicalLocationEnabled()); 100 101 // load text fields 102 dwellTimeTextField.setText(Integer.toString(Setup.getDwellTime())); 103 rfidTextField.setText(Setup.getRfidLabel()); 104 valueTextField.setText(Setup.getValueLabel()); 105 106 // add tool tips 107 saveButton.setToolTipText(Bundle.getMessage("SaveToolTip")); 108 rfidTextField.setToolTipText(Bundle.getMessage("EnterNameRfidTip")); 109 valueTextField.setToolTipText(Bundle.getMessage("EnterNameValueTip")); 110 stagingTurnCheckBox.setToolTipText(Bundle.getMessage("AlsoAvailablePerTrain")); 111 112 // load combobox, allow 2 to 4 passes 113 for (int x = 2; x < 5; x++) { 114 numberPassesComboBox.addItem(x); 115 } 116 117 numberPassesComboBox.setSelectedItem(Setup.getNumberPasses()); 118 padComboBox(numberPassesComboBox, 2); 119 120 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 121 122 JPanel panel = new JPanel(); 123 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 124 JScrollPane panelPane = new JScrollPane(panel); 125 126 // Build Options panel 127 JPanel pBuild = new JPanel(); 128 pBuild.setLayout(new BoxLayout(pBuild, BoxLayout.Y_AXIS)); 129 pBuild.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutBuildOptions"))); 130 131 JPanel pOpt = new JPanel(); 132 pOpt.setLayout(new GridBagLayout()); 133 134 addItem(pOpt, buildNormal, 1, 0); 135 addItem(pOpt, buildAggressive, 2, 0); 136 addItem(pOpt, buildOnTime, 3, 0); 137 pBuild.add(pOpt); 138 139 JPanel pPasses = new JPanel(); 140 pPasses.setLayout(new GridBagLayout()); 141 pPasses.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutNumberPasses"))); 142 addItem(pPasses, numberPassesComboBox, 0, 0); 143 pBuild.add(pPasses); 144 145 JPanel pDwellTime = new JPanel(); 146 pDwellTime.setLayout(new GridBagLayout()); 147 pDwellTime.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDwellTime"))); 148 addItem(pDwellTime, dwellTimeTextField, 0, 0); 149 pBuild.add(pDwellTime); 150 151 // Switcher Service 152 JPanel pSwitcher = new JPanel(); 153 pSwitcher.setLayout(new GridBagLayout()); 154 pSwitcher.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitcherService"))); 155 156 addItemLeft(pSwitcher, localInterchangeCheckBox, 1, 1); 157 addItemLeft(pSwitcher, localSpurCheckBox, 1, 2); 158 addItemLeft(pSwitcher, localYardCheckBox, 1, 3); 159 160 // Staging 161 JPanel pStaging = new JPanel(); 162 pStaging.setLayout(new GridBagLayout()); 163 pStaging.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutStaging"))); 164 165 addItemLeft(pStaging, trainIntoStagingCheckBox, 1, 4); 166 addItemLeft(pStaging, stagingAvailCheckBox, 1, 5); 167 addItemLeft(pStaging, stagingTurnCheckBox, 1, 6); 168 addItemLeft(pStaging, promptFromTrackStagingCheckBox, 1, 7); 169 addItemLeft(pStaging, promptToTrackStagingCheckBox, 1, 8); 170 addItemLeft(pStaging, tryNormalStagingCheckBox, 1, 9); 171 172 // Router panel 173 JPanel pRouter = new JPanel(); 174 pRouter.setLayout(new GridBagLayout()); 175 pRouter.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutRouterOptions"))); 176 addItemLeft(pRouter, routerCheckBox, 1, 0); 177 addItemLeft(pRouter, routerYardCheckBox, 1, 1); 178 addItemLeft(pRouter, routerStagingCheckBox, 1, 2); 179 addItemLeft(pRouter, routerAllTrainsBox, 1, 3); 180 addItemLeft(pRouter, routerRestrictBox, 1, 4); 181 182 // Logger panel 183 JPanel pLogger = new JPanel(); 184 pLogger.setLayout(new GridBagLayout()); 185 pLogger.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLoggerOptions"))); 186 addItemLeft(pLogger, engineLoggerCheckBox, 1, 0); 187 addItemLeft(pLogger, carLoggerCheckBox, 1, 1); 188 addItemLeft(pLogger, trainLoggerCheckBox, 1, 2); 189 190 // Custom Manifests and Switch Lists 191 JPanel pCustom = new JPanel(); 192 pCustom.setLayout(new GridBagLayout()); 193 pCustom.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutCustomManifests"))); 194 addItemLeft(pCustom, generateCvsManifestCheckBox, 1, 0); 195 addItemLeft(pCustom, generateCvsSwitchListCheckBox, 1, 1); 196 197 // Options 198 JPanel pOption = new JPanel(); 199 pOption.setLayout(new GridBagLayout()); 200 pOption.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptions"))); 201 addItemLeft(pOption, saveTrainManifestCheckBox, 1, 1); 202 addItemLeft(pOption, valueCheckBox, 1, 2); 203 addItemLeft(pOption, valueTextField, 2, 2); 204 addItemLeft(pOption, rfidCheckBox, 1, 3); 205 addItemLeft(pOption, rfidTextField, 2, 3); 206 addItemLeft(pOption, enableVsdCheckBox, 1, 4); 207 208 // row 11 209 JPanel pControl = new JPanel(); 210 pControl.setLayout(new GridBagLayout()); 211 addItem(pControl, saveButton, 3, 9); 212 213 panel.add(pBuild); 214 panel.add(pSwitcher); 215 panel.add(pStaging); 216 panel.add(pRouter); 217 panel.add(pLogger); 218 panel.add(pCustom); 219 panel.add(pOption); 220 221 add(panelPane); 222 add(pControl); 223 224 // setup buttons 225 addButtonAction(saveButton); 226 227 // radio buttons 228 ButtonGroup buildGroup = new ButtonGroup(); 229 buildGroup.add(buildNormal); 230 buildGroup.add(buildAggressive); 231 buildGroup.add(buildOnTime); 232 233 addRadioButtonAction(buildNormal); 234 addRadioButtonAction(buildAggressive); 235 addRadioButtonAction(buildOnTime); 236 237 // check boxes 238 addCheckBoxAction(routerCheckBox); 239 addCheckBoxAction(routerRestrictBox); 240 setRouterCheckBoxesEnabled(); 241 242 setBuildOption(); 243 enableComponents(); 244 } 245 246 private void setBuildOption() { 247 buildNormal.setSelected(!Setup.isBuildAggressive()); 248 buildAggressive.setSelected(Setup.isBuildAggressive()); 249 buildOnTime.setSelected(Setup.isBuildOnTime()); 250 } 251 252 private void enableComponents() { 253 // disable staging option if normal mode 254 stagingAvailCheckBox.setEnabled(!buildNormal.isSelected()); 255 numberPassesComboBox.setEnabled(!buildNormal.isSelected()); 256 dwellTimeTextField.setEnabled(buildOnTime.isSelected()); 257 tryNormalStagingCheckBox.setEnabled(!buildNormal.isSelected()); 258 } 259 260 @Override 261 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 262 log.debug("radio button selected"); 263 // can't change the build option if there are trains built 264 if (InstanceManager.getDefault(TrainManager.class).isAnyTrainBuilt()) { 265 setBuildOption(); // restore the correct setting 266 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("CanNotChangeBuild"), 267 Bundle.getMessage("MustTerminateOrReset"), JmriJOptionPane.ERROR_MESSAGE); 268 } 269 enableComponents(); 270 // Special case where there are train build failures that created work. 271 // Track reserve needs to cleaned up by reseting build failed trains 272 if (buildAggressive.isSelected() != Setup.isBuildAggressive() && 273 InstanceManager.getDefault(LocationManager.class).hasWork()) { 274 InstanceManager.getDefault(TrainManager.class).resetBuildFailedTrains(); 275 } 276 } 277 278 // Save button 279 @Override 280 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 281 if (ae.getSource() == saveButton) { 282 this.savePreferences(); 283 var topLevelAncestor = getTopLevelAncestor(); 284 if (Setup.isCloseWindowOnSaveEnabled() && topLevelAncestor instanceof OptionFrame) { 285 ((OptionFrame) topLevelAncestor).dispose(); 286 } 287 } 288 } 289 290 @Override 291 protected void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 292 if (ae.getSource() == routerCheckBox) { 293 setRouterCheckBoxesEnabled(); 294 } 295 if (ae.getSource() == routerRestrictBox && routerRestrictBox.isSelected()) { 296 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("WarnExtremeTrackDest"), 297 Bundle.getMessage("WarnExtremeTitle"), JmriJOptionPane.WARNING_MESSAGE); 298 } 299 } 300 301 private void setRouterCheckBoxesEnabled() { 302 routerYardCheckBox.setEnabled(routerCheckBox.isSelected()); 303 routerStagingCheckBox.setEnabled(routerCheckBox.isSelected()); 304 routerAllTrainsBox.setEnabled(routerCheckBox.isSelected()); 305 routerRestrictBox.setEnabled(routerCheckBox.isSelected()); 306 } 307 308 @Override 309 public String getTabbedPreferencesTitle() { 310 return Bundle.getMessage("TitleOptions"); 311 } 312 313 @Override 314 public String getPreferencesTooltip() { 315 return null; 316 } 317 318 @Override 319 public void savePreferences() { 320 // build option 321 boolean isBuildOnTime = Setup.isBuildOnTime(); 322 Setup.setBuildAggressive(buildAggressive.isSelected() || buildOnTime.isSelected()); 323 Setup.setNumberPasses((Integer) numberPassesComboBox.getSelectedItem()); 324 Setup.setBuildOnTime(buildOnTime.isSelected()); 325 try { 326 Setup.setDwellTime(Integer.parseInt(dwellTimeTextField.getText())); 327 } catch (NumberFormatException e) { 328 log.error("Dwell Time {} must be a number", dwellTimeTextField.getText()); 329 } 330 // local switcher options 331 Setup.setLocalInterchangeMovesEnabled(localInterchangeCheckBox.isSelected()); 332 Setup.setLocalSpurMovesEnabled(localSpurCheckBox.isSelected()); 333 Setup.setLocalYardMovesEnabled(localYardCheckBox.isSelected()); 334 // Staging options 335 Setup.setStagingTrainCheckEnabled(trainIntoStagingCheckBox.isSelected()); 336 Setup.setStagingTrackImmediatelyAvail(stagingAvailCheckBox.isSelected()); 337 Setup.setStagingAllowReturnEnabled(stagingTurnCheckBox.isSelected()); 338 Setup.setStagingPromptFromEnabled(promptFromTrackStagingCheckBox.isSelected()); 339 Setup.setStagingPromptToEnabled(promptToTrackStagingCheckBox.isSelected()); 340 Setup.setStagingTryNormalBuildEnabled(tryNormalStagingCheckBox.isSelected()); 341 // Car routing enabled? 342 Setup.setCarRoutingEnabled(routerCheckBox.isSelected()); 343 Setup.setCarRoutingViaYardsEnabled(routerYardCheckBox.isSelected()); 344 Setup.setCarRoutingViaStagingEnabled(routerStagingCheckBox.isSelected()); 345 Setup.setOnlyActiveTrainsEnabled(!routerAllTrainsBox.isSelected()); 346 Setup.setCheckCarDestinationEnabled(routerRestrictBox.isSelected()); 347 // Options 348 Setup.setGenerateCsvManifestEnabled(generateCvsManifestCheckBox.isSelected()); 349 Setup.setGenerateCsvSwitchListEnabled(generateCvsSwitchListCheckBox.isSelected()); 350 Setup.setSaveTrainManifestsEnabled(saveTrainManifestCheckBox.isSelected()); 351 Setup.setValueEnabled(valueCheckBox.isSelected()); 352 Setup.setValueLabel(valueTextField.getText()); 353 Setup.setRfidEnabled(rfidCheckBox.isSelected()); 354 Setup.setRfidLabel(rfidTextField.getText()); 355 // Logging enabled? 356 Setup.setEngineLoggerEnabled(engineLoggerCheckBox.isSelected()); 357 Setup.setCarLoggerEnabled(carLoggerCheckBox.isSelected()); 358 Setup.setTrainLoggerEnabled(trainLoggerCheckBox.isSelected()); 359 // VSD 360 Setup.setVsdPhysicalLocationEnabled(enableVsdCheckBox.isSelected()); 361 // write the file 362 OperationsXml.save(); 363 // bring up the quick service tool 364 if (!isBuildOnTime && buildOnTime.isSelected()) { 365 LocationsByQuickServiceFrame f = new LocationsByQuickServiceFrame(); 366 f.initComponents(); 367 } 368 } 369 370 @Override 371 public boolean isDirty() { 372 return !( // build option 373 Setup.isBuildAggressive() == buildAggressive.isSelected() && 374 Setup.getNumberPasses() == (int) numberPassesComboBox.getSelectedItem() 375 // Local moves? 376 && 377 Setup.isLocalInterchangeMovesEnabled() == localInterchangeCheckBox.isSelected() && 378 Setup.isLocalSpurMovesEnabled() == localSpurCheckBox.isSelected() && 379 Setup.isLocalYardMovesEnabled() == localYardCheckBox.isSelected() 380 // Staging options 381 && 382 Setup.isStagingTrainCheckEnabled() == trainIntoStagingCheckBox.isSelected() && 383 Setup.isStagingTrackImmediatelyAvail() == stagingAvailCheckBox.isSelected() && 384 Setup.isStagingAllowReturnEnabled() == stagingTurnCheckBox.isSelected() && 385 Setup.isStagingPromptFromEnabled() == promptFromTrackStagingCheckBox.isSelected() && 386 Setup.isStagingPromptToEnabled() == promptToTrackStagingCheckBox.isSelected() && 387 Setup.isStagingTryNormalBuildEnabled() == tryNormalStagingCheckBox.isSelected() 388 // Car routing enabled? 389 && 390 Setup.isCarRoutingEnabled() == routerCheckBox.isSelected() && 391 Setup.isCarRoutingViaYardsEnabled() == routerYardCheckBox.isSelected() && 392 Setup.isCarRoutingViaStagingEnabled() == routerStagingCheckBox.isSelected() && 393 Setup.isOnlyActiveTrainsEnabled() == !routerAllTrainsBox.isSelected() && 394 Setup.isCheckCarDestinationEnabled() == routerRestrictBox.isSelected() 395 // Options 396 && 397 Setup.isGenerateCsvManifestEnabled() == generateCvsManifestCheckBox.isSelected() && 398 Setup.isGenerateCsvSwitchListEnabled() == generateCvsSwitchListCheckBox.isSelected() && 399 Setup.isValueEnabled() == valueCheckBox.isSelected() && 400 Setup.getValueLabel().equals(valueTextField.getText()) && 401 Setup.isRfidEnabled() == rfidCheckBox.isSelected() && 402 Setup.getRfidLabel().equals(rfidTextField.getText()) && 403 Setup.isSaveTrainManifestsEnabled() == saveTrainManifestCheckBox.isSelected() 404 // Logging enabled? 405 && 406 Setup.isEngineLoggerEnabled() == engineLoggerCheckBox.isSelected() && 407 Setup.isCarLoggerEnabled() == carLoggerCheckBox.isSelected() && 408 Setup.isTrainLoggerEnabled() == trainLoggerCheckBox.isSelected() 409 // VSD 410 && 411 Setup.isVsdPhysicalLocationEnabled() == enableVsdCheckBox.isSelected()); 412 } 413 414 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OptionPanel.class); 415 416}