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