001package jmri.jmrit.operations.setup;
002
003import java.awt.GridBagLayout;
004
005import javax.swing.*;
006
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010import jmri.InstanceManager;
011import jmri.jmrit.operations.locations.LocationManager;
012import jmri.jmrit.operations.trains.TrainManager;
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        addItem(pBuild, pOpt, 1, 0);
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        addItem(pBuild, pPasses, 1, 1);
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        addItemLeft(pBuild, pSwitcher, 1, 2);
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        addItemLeft(pBuild, pStaging, 1, 3);
161
162        // Router panel
163        JPanel pRouter = new JPanel();
164        pRouter.setLayout(new GridBagLayout());
165        pRouter.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutRouterOptions")));
166        addItemLeft(pRouter, routerCheckBox, 1, 0);
167        addItemLeft(pRouter, routerYardCheckBox, 1, 1);
168        addItemLeft(pRouter, routerStagingCheckBox, 1, 2);
169        addItemLeft(pRouter, routerAllTrainsBox, 1, 3);
170        addItemLeft(pRouter, routerRestrictBox, 1, 4);
171
172        // Logger panel
173        JPanel pLogger = new JPanel();
174        pLogger.setLayout(new GridBagLayout());
175        pLogger.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLoggerOptions")));
176        addItemLeft(pLogger, engineLoggerCheckBox, 1, 0);
177        addItemLeft(pLogger, carLoggerCheckBox, 1, 1);
178        addItemLeft(pLogger, trainLoggerCheckBox, 1, 2);
179
180        // Custom Manifests and Switch Lists
181        JPanel pCustom = new JPanel();
182        pCustom.setLayout(new GridBagLayout());
183        pCustom.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutCustomManifests")));
184        addItemLeft(pCustom, generateCvsManifestCheckBox, 1, 0);
185        addItemLeft(pCustom, generateCvsSwitchListCheckBox, 1, 1);
186
187        // Options
188        JPanel pOption = new JPanel();
189        pOption.setLayout(new GridBagLayout());
190        pOption.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptions")));
191        addItemLeft(pOption, saveTrainManifestCheckBox, 1, 1);
192        addItemLeft(pOption, valueCheckBox, 1, 2);
193        addItemLeft(pOption, valueTextField, 2, 2);
194        addItemLeft(pOption, rfidCheckBox, 1, 3);
195        addItemLeft(pOption, rfidTextField, 2, 3);
196        addItemLeft(pOption, enableVsdCheckBox, 1, 4);
197
198        // row 11
199        JPanel pControl = new JPanel();
200        pControl.setLayout(new GridBagLayout());
201        addItem(pControl, saveButton, 3, 9);
202
203        panel.add(pBuild);
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            JOptionPane.showMessageDialog(this, Bundle.getMessage("CanNotChangeBuild"),
250                    Bundle.getMessage("MustTerminateOrReset"), JOptionPane.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            if (Setup.isCloseWindowOnSaveEnabled()) {
267                dispose();
268            }
269        }
270    }
271
272    @Override
273    protected void checkBoxActionPerformed(java.awt.event.ActionEvent ae) {
274        if (ae.getSource() == routerCheckBox) {
275            setRouterCheckBoxesEnabled();
276        }
277        if (ae.getSource() == routerRestrictBox && routerRestrictBox.isSelected()) {
278            JOptionPane.showMessageDialog(this, Bundle.getMessage("WarnExtremeTrackDest"),
279                    Bundle.getMessage("WarnExtremeTitle"), JOptionPane.WARNING_MESSAGE);
280        }
281    }
282
283    private void setRouterCheckBoxesEnabled() {
284        routerYardCheckBox.setEnabled(routerCheckBox.isSelected());
285        routerStagingCheckBox.setEnabled(routerCheckBox.isSelected());
286        routerAllTrainsBox.setEnabled(routerCheckBox.isSelected());
287        routerRestrictBox.setEnabled(routerCheckBox.isSelected());
288    }
289
290    private static final Logger log = LoggerFactory.getLogger(OptionPanel.class);
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}