001package jmri.jmrix.can.cbus.swing.modeswitcher;
002
003import java.awt.BorderLayout;
004import java.awt.event.ActionListener;
005
006import javax.swing.*;
007
008import jmri.InstanceManager;
009import jmri.jmrix.can.*;
010import jmri.jmrix.can.cbus.CbusConsistManager;
011import jmri.util.swing.JmriJOptionPane;
012
013/**
014 * Mode Switcher to switch modes between programmer and command station for simple
015 * hardware with a single track output.
016 *
017 * @author Andrew Crosland Copyright (C) 2020, 2021
018 */
019public class SprogCbusSimpleModeSwitcherFrame extends SprogCbusModeSwitcherFrame {
020    
021    protected static final int PROG_MODE = 0;     // Original SPROG Programnmer mode
022    protected static final int CMD_MODE = 1;      // Original SPROG Command Station mode
023
024    private JRadioButton progModeButton;
025    private JRadioButton cmdModeButton;
026
027    public SprogCbusSimpleModeSwitcherFrame(CanSystemConnectionMemo memo) {
028        super(memo, Bundle.getMessage("SprogCbusSimpleModeSwitcher"));
029    }
030    
031    
032    /**
033     * Display radio buttons to select between Programmer mode (service mode
034     * programming) and command station  mode (ops mode programming).
035     * <p>
036     * Only one mode may be selected at a time.
037     * <p>
038     * At least one mode must be enabled and the default is programmer mode if
039     * all modes are deselected.
040     * 
041     * {@inheritDoc}
042     */
043    @Override
044    public void initComponents() {
045        if (initSetup()) {
046            // Create selection buttons, add to exclusive group and set initial state from preferences
047            progModeButton = new JRadioButton(Bundle.getMessage("ProgMode"));
048            cmdModeButton = new JRadioButton(Bundle.getMessage("CmdMode"));
049            ButtonGroup buttons = new ButtonGroup();
050            buttons.add(progModeButton);
051            buttons.add(cmdModeButton);
052            
053            // Get current preferences
054            // It is expected that the saved preferences will usually match the hardware.
055            if (pm.isGlobalProgrammerAvailable() && preferences.isGlobalProgrammerAvailable()) {
056                // Programmer (service) mode
057                progModeButton.setSelected(true);
058                cmdModeButton.setSelected(false);
059                mode = PROG_MODE;
060                _memo.setMultipleThrottles(false);
061            } else if (pm.isAddressedModePossible() && preferences.isAddressedModePossible()) {
062                // Command Station (ops, addressed) mode
063                progModeButton.setSelected(false);
064                cmdModeButton.setSelected(true);
065                mode = CMD_MODE;
066                _memo.setMultipleThrottles(true);
067            } else {
068                // Default to programmer (service) mode if inconsistent preference
069                progModeButton.setSelected(true);
070                cmdModeButton.setSelected(false);
071                mode = PROG_MODE;
072                _memo.setMultipleThrottles(false);
073            }
074            // Reset hardware mode and preferences in case there was any inconsistency
075            setHardwareMode(mode);
076            preferences.setProgrammersAvailable(progModeButton.isSelected(), cmdModeButton.isSelected());
077
078            // Handle Programmer mode button activity
079            ActionListener listener = ae -> {
080                CbusConsistManager cm = (CbusConsistManager)InstanceManager.getNullableDefault(jmri.ConsistManager.class);
081                if (progModeButton.isSelected() && mode != PROG_MODE) {
082                    // Switch to programmer mode
083                    log.info("Setting Global Programmer Available");
084                    pm.setGlobalProgrammerAvailable(true);
085                    log.info("Setting Addressed Programmer Unavailable");
086                    pm.setAddressedModePossible(false);
087                    _memo.setMultipleThrottles(false);
088                    showServiceModeWarningDialogue();
089                    closeProgrammerWarningDialogue();
090                    if (cm != null) {
091                        cm.setEnabled(false);
092                    }
093                    mode = PROG_MODE;
094                } else if (cmdModeButton.isSelected() && mode != CMD_MODE) {
095                    // Switch to command station mode
096                    log.info("Setting Global Programmer Unavailable");
097                    pm.setGlobalProgrammerAvailable(false);
098                    log.info("Setting Addressed Programmer Available");
099                    pm.setAddressedModePossible(true);
100                    _memo.setMultipleThrottles(true);
101                    closeProgrammerWarningDialogue();
102                    if (cm != null) {
103                        cm.setEnabled(true);
104                    }
105                    mode = CMD_MODE;
106                }
107                setHardwareMode(mode);
108                preferences.setProgrammersAvailable(progModeButton.isSelected(), cmdModeButton.isSelected());
109            };
110
111            progModeButton.addActionListener(listener);
112            cmdModeButton.addActionListener(listener);
113            modePane.add(progModeButton);
114            modePane.add(cmdModeButton);
115
116            panel.add(label, BorderLayout.NORTH);
117            panel.add(modePane, BorderLayout.CENTER);
118        }
119        
120        // add help menu to window
121        setHelp();
122
123        this.add(panel);
124        pack();
125        setVisible(true);
126    }
127
128    private boolean _hideProgWarning = false;
129
130    protected void closeProgrammerWarningDialogue(){
131        if ((!java.awt.GraphicsEnvironment.isHeadless()) && (!_hideProgWarning)){
132            jmri.util.ThreadingUtil.runOnGUI(() -> {
133                javax.swing.JCheckBox checkbox = new javax.swing.JCheckBox(Bundle.getMessage("HideFurtherWarnings"));
134                java.awt.event.ActionListener progPopUpCheckBox = (java.awt.event.ActionEvent evt) -> hideProgWarning(checkbox.isSelected());
135                checkbox.addActionListener(progPopUpCheckBox);
136                Object[] params = {Bundle.getMessage("ProgWarning"), checkbox};
137                JmriJOptionPane.showMessageDialogNonModal(null, params,
138                    Bundle.getMessage("switchMode"),
139                    JmriJOptionPane.WARNING_MESSAGE, null);
140            });
141        }
142    }
143
144    /**
145     * Receive notification from a mode switcher dialogue to close programmer when
146     * switching modes. This so buttons correctly reflect available operations.
147     * False by default to show notifications
148     *
149     * @param hide set True to hide notifications, else False.
150     */
151    public void hideProgWarning(boolean hide){
152        _hideProgWarning = hide;
153    }
154
155    private boolean _hideProgModeWarning = false;
156
157    protected void showServiceModeWarningDialogue(){
158        if ((!java.awt.GraphicsEnvironment.isHeadless()) && (!_hideProgModeWarning)){
159            jmri.util.ThreadingUtil.runOnGUI(() -> {
160                javax.swing.JCheckBox checkbox = new javax.swing.JCheckBox(Bundle.getMessage("HideFurtherWarnings"));
161                Object[] params = {Bundle.getMessage("ProgModeWarning"), checkbox};
162                java.awt.event.ActionListener progPopUpCheckBox = (java.awt.event.ActionEvent evt) -> hideProgModeWarning(checkbox.isSelected());
163                checkbox.addActionListener(progPopUpCheckBox);
164                JmriJOptionPane.showMessageDialogNonModal(null,params,
165                    Bundle.getMessage("switchToProgMode"),
166                    JmriJOptionPane.WARNING_MESSAGE, null);
167            });
168        }
169    }
170
171    /**
172     * Receive notification from a mode switcher dialogue to display warning
173     * message about service mode programminf.
174     * False by default to show notifications
175     *
176     * @param hide set True to hide notifications, else False.
177     */
178    public void hideProgModeWarning(boolean hide){
179        _hideProgModeWarning = hide;
180    }
181
182    /**
183     * Define help menu for this window.
184     */
185    protected void setHelp() {
186        addHelpMenu("package.jmri.jmrix.can.cbus.swing.modeswitcher.SprogCbusSimpleModeSwitcherFrame", true); // NOI18N
187    }
188
189    
190    /**
191     * disconnect from the CBUS
192     */
193    @Override
194    public void dispose() {
195        super.dispose();
196    }
197
198    
199    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SprogCbusSimpleModeSwitcherFrame.class);
200    
201}