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