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