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