001package jmri.jmrix;
002
003import java.awt.Color;
004import java.awt.GridBagConstraints;
005import java.awt.Insets;
006import java.awt.event.ActionEvent;
007import java.util.Map;
008import javax.swing.JComboBox;
009import javax.swing.JComponent;
010import javax.swing.JPanel;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 * Abstract base class for common implementation of the Simulator
016 * ConnectionConfig.
017 * <p>
018 * Currently uses the SerialPortAdapter, but this will change to
019 * the simulator adapter in due course.
020 *
021 * @author Kevin Dickerson Copyright (C) 2001, 2003
022 */
023abstract public class AbstractSimulatorConnectionConfig extends AbstractConnectionConfig {
024
025    /**
026     * Create a connection configuration with a preexisting adapter. This is
027     * used principally when loading a configuration that defines this
028     * connection.
029     *
030     * @param p the adapter to create a connection configuration for
031     */
032    public AbstractSimulatorConnectionConfig(jmri.jmrix.SerialPortAdapter p) {
033        adapter = p;
034    }
035
036    @Override
037    public jmri.jmrix.SerialPortAdapter getAdapter() {
038        return adapter;
039    }
040
041    /**
042     * Ctor for a functional object with no preexisting adapter. Expect that the
043     * subclass setInstance() will fill the adapter member.
044     */
045    public AbstractSimulatorConnectionConfig() {
046        log.debug("AbstractSimulatorConnectionConfig null ctor used");
047        adapter = null;
048    }
049
050    protected boolean init = false;
051
052    /**
053     * {@inheritDoc}
054     */
055    @Override
056    protected void checkInitDone() {
057        log.debug("init called for {}", name());
058        if (init) {
059            return;
060        }
061        addNameEntryCheckers(adapter);
062
063        // Add listeners for advanced options combo boxes.
064        for (Map.Entry<String, Option> entry : options.entrySet()) {
065            final String item = entry.getKey();
066            if (entry.getValue().getComponent() instanceof JComboBox) {
067                ((JComboBox<?>) entry.getValue().getComponent()).addActionListener((ActionEvent e) -> {
068                    adapter.setOptionState(item, options.get(item).getItem());
069                });
070            }
071        }
072
073        init = true;
074    }
075
076    @Override
077    public void updateAdapter() {
078        for (Map.Entry<String, Option> entry : options.entrySet()) {
079            adapter.setOptionState(entry.getKey(), entry.getValue().getItem());
080        }
081
082        if (!adapter.getSystemConnectionMemo().setSystemPrefix(systemPrefixField.getText())) {
083            systemPrefixField.setText(adapter.getSystemConnectionMemo().getSystemPrefix());
084            connectionNameField.setText(adapter.getSystemConnectionMemo().getUserName());
085        }
086    }
087
088    protected String[] baudList;
089    protected jmri.jmrix.SerialPortAdapter adapter;
090
091    /**
092     * {@inheritDoc}
093     */
094    @Override
095    abstract protected void setInstance();
096
097    /**
098     * {@inheritDoc}
099     * <p>
100     * This implementation always returns the localized value for "none".
101     *
102     * @return the localized value for "none"
103     */
104    @Override
105    public String getInfo() {
106        return Bundle.getMessage("none");
107    }
108
109    /**
110     * {@inheritDoc}
111     */
112    @Override
113    public void loadDetails(final JPanel details) {
114        _details = details;
115        setInstance();
116        if (!init) {
117            String[] optionsAvailable = adapter.getOptions();
118            options.clear();
119            for (String i : optionsAvailable) {
120                JComboBox<String> opt = new JComboBox<>(adapter.getOptionChoices(i));
121                opt.setSelectedItem(adapter.getOptionState(i));
122                // check that it worked
123                if (!adapter.getOptionState(i).equals(opt.getSelectedItem())) {
124                    // no, set 1st option choice
125                    opt.setSelectedIndex(0);
126                    // log before setting new value to show old value
127                    log.warn("Loading found invalid value for option {}, found \"{}\", setting to \"{}\"", i, adapter.getOptionState(i), opt.getSelectedItem());
128                    adapter.setOptionState(i, (String) opt.getSelectedItem());
129                }
130                options.put(i, new Option(adapter.getOptionDisplayName(i), opt, adapter.isOptionAdvanced(i)));
131            }
132        }
133
134        if (adapter.getSystemConnectionMemo() != null) {
135            systemPrefixField.setText(adapter.getSystemConnectionMemo().getSystemPrefix());
136            connectionNameField.setText(adapter.getSystemConnectionMemo().getUserName());
137        }
138        NUMOPTIONS = NUMOPTIONS + options.size();
139
140        showAdvanced.setFont(showAdvanced.getFont().deriveFont(9f));
141        showAdvanced.setForeground(Color.blue);
142        showAdvanced.addItemListener(e -> showAdvancedItems());
143        showAdvancedItems();
144        init = false;  // need to reload action listeners
145        checkInitDone();
146    }
147
148    @Override
149    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE",
150        justification = "Type is checked before casting")
151    protected void showAdvancedItems() {
152        _details.removeAll();
153        cL.anchor = GridBagConstraints.WEST;
154        cL.insets = new Insets(2, 5, 0, 5);
155        cR.insets = new Insets(2, 0, 0, 5);
156        cR.anchor = GridBagConstraints.WEST;
157        cR.gridx = 1;
158        cL.gridx = 0;
159        _details.setLayout(gbLayout);
160        int i = 0;
161
162        boolean incAdvancedOptions = false;
163        for (Map.Entry<String, Option> entry : options.entrySet()) {
164            if (entry.getValue().isAdvanced()) {
165                incAdvancedOptions = true;
166            }
167        }
168
169        i = addStandardDetails(adapter, incAdvancedOptions, i);
170
171        if (showAdvanced.isSelected()) {
172            for (Map.Entry<String, Option> entry : options.entrySet()) {
173                if (entry.getValue().isAdvanced()) {
174                    cR.gridy = i;
175                    cL.gridy = i;
176                    gbLayout.setConstraints(entry.getValue().getLabel(), cL);
177                    gbLayout.setConstraints(entry.getValue().getComponent(), cR);
178                    _details.add(entry.getValue().getLabel());
179                    _details.add(entry.getValue().getComponent());
180                    i++;
181                }
182            }
183        }
184        cL.gridwidth = 2;
185        for (JComponent item : additionalItems) {
186            cL.gridy = i;
187            gbLayout.setConstraints(item, cL);
188            _details.add(item);
189            i++;
190        }
191        cL.gridwidth = 1;
192        if (_details.getParent() != null && _details.getParent() instanceof javax.swing.JViewport) {
193            javax.swing.JViewport vp = (javax.swing.JViewport) _details.getParent();
194            vp.revalidate();
195            vp.repaint();
196        }
197    }
198
199    @Override
200    public String getManufacturer() {
201        return adapter.getManufacturer();
202    }
203
204    @Override
205    public void setManufacturer(String manufacturer) {
206        setInstance();
207        adapter.setManufacturer(manufacturer);
208    }
209
210    @Override
211    public String getConnectionName() {
212        if (adapter.getSystemConnectionMemo() != null) {
213            return adapter.getSystemConnectionMemo().getUserName();
214        } else {
215            return null;
216        }
217    }
218
219    @Override
220    public boolean getDisabled() {
221        if (adapter == null) {
222            return true;
223        }
224        return adapter.getDisabled();
225    }
226
227    @Override
228    public void setDisabled(boolean disabled) {
229        adapter.setDisabled(disabled);
230    }
231
232    @Override
233    public void dispose() {
234        super.dispose();
235        if (adapter != null) {
236            adapter.dispose();
237            adapter = null;
238        }
239    }
240
241    private final static Logger log = LoggerFactory.getLogger(AbstractSimulatorConnectionConfig.class);
242
243}