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