001package jmri.jmrit.blockboss;
002
003import java.awt.Color;
004import java.awt.FlowLayout;
005import java.awt.GridBagConstraints;
006import java.awt.GridBagLayout;
007import java.awt.Insets;
008import java.awt.event.ActionListener;
009import javax.annotation.Nonnull;
010import javax.swing.*;
011
012import jmri.InstanceManager;
013import jmri.Sensor;
014import jmri.SensorManager;
015import jmri.SignalHead;
016import jmri.SignalHeadManager;
017import jmri.Turnout;
018import jmri.NamedBean.DisplayOptions;
019import jmri.swing.NamedBeanComboBox;
020import jmri.util.swing.JmriJOptionPane;
021
022/**
023 * Provide a GUI for configuring "Simple Signal Logic" (BlockBossLogic) objects.
024 * <p>
025 * Provides four panels, corresponding to the four possible modes described in
026 * {@link BlockBossLogic}, which are then selected via radio buttons in the GUI.
027 * <p>
028 * The four modes are:
029 * <ul>
030 * <li>Single block (s)
031 * <li>Facing point (f)
032 * <li>Trailing point main (tm)
033 * <li>Trailing point diverging (td)
034 * </ul>
035 * <p>
036 * The multiple-panel approach to the GUI is used to make layout easier; the
037 * code just flips from one to the other as the user selects a mode. The
038 * individual items all share data models to simplify the logic.
039 *
040 * @author Bob Jacobsen Copyright (C) 2003, 2005
041 * @author Dick Bronson 2006: Revisions to add facing point sensors,
042 * approach lighting, limited speed, changed layout, and tool tips.
043 * @author Egbert Broerse 2017
044 */
045public class BlockBossFrame extends jmri.util.JmriJFrame {
046
047    private static final String SIMPLE_SIGNAL_LOGIC = "Simple_Signal_Logic";
048    private static final String LIMITED_SPEED = "Limited_Speed";
049    private static final String RESTRICTING_SPEED = "Restricting_Speed";
050    private static final String WITH_FLASHING_YELLOW = "With_Flashing_Yellow";
051    private static final String PROTECTS_SENSOR = "ProtectsSensor";
052    private static final String IS_DISTANT_SIGNAL = "Is_Distant_Signal";
053    private static final String PROTECTS_SIGNAL = "Protects_Signal";
054    private final JPanel modeSingle = new JPanel();
055    private final JRadioButton buttonSingle;
056    private final transient NamedBeanComboBox<Sensor> sSensorComboBox1 = new NamedBeanComboBox<>(
057            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
058    private final transient NamedBeanComboBox<Sensor> sSensorComboBox2 = new NamedBeanComboBox<>(
059            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
060    private final transient NamedBeanComboBox<Sensor> sSensorComboBox3 = new NamedBeanComboBox<>(
061            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
062    private final transient NamedBeanComboBox<Sensor> sSensorComboBox4 = new NamedBeanComboBox<>(
063            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
064    private final transient NamedBeanComboBox<Sensor> sSensorComboBox5 = new NamedBeanComboBox<>(
065            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
066    private final transient NamedBeanComboBox<SignalHead> sNextSignalComboBox1 = new NamedBeanComboBox<>(
067            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
068    private final transient NamedBeanComboBox<SignalHead> sNextSignalComboBox1Alt = new NamedBeanComboBox<>(
069            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
070    private final JCheckBox sLimitBox;
071    private final JCheckBox sRestrictingBox;
072    private final JCheckBox sFlashBox;
073    private final JCheckBox sDistantBox;
074
075    private final JPanel modeTrailMain = new JPanel();
076    private final JRadioButton buttonTrailMain;
077    private final transient NamedBeanComboBox<Sensor> tmSensorComboBox1 = new NamedBeanComboBox<>(
078            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
079    private final transient NamedBeanComboBox<Sensor> tmSensorComboBox2 = new NamedBeanComboBox<>(
080            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
081    private final transient NamedBeanComboBox<Sensor> tmSensorComboBox3 = new NamedBeanComboBox<>(
082            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
083    private final transient NamedBeanComboBox<Sensor> tmSensorComboBox4 = new NamedBeanComboBox<>(
084            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
085    private final transient NamedBeanComboBox<Sensor> tmSensorComboBox5 = new NamedBeanComboBox<>(
086            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
087    private final NamedBeanComboBox<Turnout> tmProtectTurnoutComboBox = new NamedBeanComboBox<>(
088            InstanceManager.turnoutManagerInstance(),
089            null, DisplayOptions.DISPLAYNAME);
090    private final transient NamedBeanComboBox<SignalHead> tmNextSignalComboBox1 = new NamedBeanComboBox<>(
091            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
092    private final transient NamedBeanComboBox<SignalHead> tmNextSignalComboBox1Alt = new NamedBeanComboBox<>(
093            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
094    private final JCheckBox tmLimitBox;
095    private final JCheckBox tmRestrictingBox;
096    private final JCheckBox tmFlashBox;
097    private final JCheckBox tmDistantBox;
098
099    private final JPanel modeTrailDiv = new JPanel();
100    private final JRadioButton buttonTrailDiv;
101    private final transient NamedBeanComboBox<Sensor> tdSensorComboBox1 = new NamedBeanComboBox<>(
102            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
103    private final transient NamedBeanComboBox<Sensor> tdSensorComboBox2 = new NamedBeanComboBox<>(
104            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
105    private final transient NamedBeanComboBox<Sensor> tdSensorComboBox3 = new NamedBeanComboBox<>(
106            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
107    private final transient NamedBeanComboBox<Sensor> tdSensorComboBox4 = new NamedBeanComboBox<>(
108            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
109    private final transient NamedBeanComboBox<Sensor> tdSensorComboBox5 = new NamedBeanComboBox<>(
110            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
111    private final NamedBeanComboBox<Turnout> tdProtectTurnoutComboBox = new NamedBeanComboBox<>(
112            InstanceManager.turnoutManagerInstance(),
113            null, DisplayOptions.DISPLAYNAME);
114    private final transient NamedBeanComboBox<SignalHead> tdNextSignalComboBox1 = new NamedBeanComboBox<>(
115            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
116    private final transient NamedBeanComboBox<SignalHead> tdNextSignalComboBox1Alt = new NamedBeanComboBox<>(
117            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
118    private final JCheckBox tdLimitBox;
119    private final JCheckBox tdRestrictingBox;
120    private final JCheckBox tdFlashBox;
121    private final JCheckBox tdDistantBox;
122
123    private final JPanel modeFacing = new JPanel();
124    private final JRadioButton buttonFacing;
125
126    private final transient NamedBeanComboBox<Sensor> fSensorComboBox1 = new NamedBeanComboBox<>(
127            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
128    private final transient NamedBeanComboBox<Sensor> fSensorComboBox2 = new NamedBeanComboBox<>(
129            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
130    private final transient NamedBeanComboBox<Sensor> fSensorComboBox3 = new NamedBeanComboBox<>(
131            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
132    private final transient NamedBeanComboBox<Sensor> fSensorComboBox4 = new NamedBeanComboBox<>(
133            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
134    private final transient NamedBeanComboBox<Sensor> fSensorComboBox5 = new NamedBeanComboBox<>(
135            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
136    private final NamedBeanComboBox<Turnout> fProtectTurnoutComboBox = new NamedBeanComboBox<>(
137            InstanceManager.turnoutManagerInstance(),
138            null, DisplayOptions.DISPLAYNAME);
139    private final transient NamedBeanComboBox<SignalHead> fNextSignalComboBox1 = new NamedBeanComboBox<>(
140            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
141    private final transient NamedBeanComboBox<SignalHead> fNextSignalComboBox1Alt = new NamedBeanComboBox<>(
142            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
143    private final transient NamedBeanComboBox<SignalHead> fNextSignalComboBox2 = new NamedBeanComboBox<>(
144            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
145    private final transient NamedBeanComboBox<SignalHead> fNextSignalComboBox2Alt = new NamedBeanComboBox<>(
146            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
147    private final transient NamedBeanComboBox<Sensor> fNextSensorComboBox1 = new NamedBeanComboBox<>(
148            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
149    private final transient NamedBeanComboBox<Sensor> fNextSensorComboBox1Alt = new NamedBeanComboBox<>(
150            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
151    private final transient NamedBeanComboBox<Sensor> fNextSensorComboBox2 = new NamedBeanComboBox<>(
152            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
153    private final transient NamedBeanComboBox<Sensor> fNextSensorComboBox2Alt = new NamedBeanComboBox<>(
154            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
155    private final JCheckBox fmLimitBox;
156    private final JCheckBox fmRestrictingBox;
157    private final JCheckBox fdLimitBox;
158    private final JCheckBox fdRestrictingBox;
159    private final JCheckBox fFlashBox;
160    private final JCheckBox fDistantBox;
161
162    private final transient NamedBeanComboBox<Sensor> approachSensor1ComboBox = new NamedBeanComboBox<>(
163            InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME);
164    private final transient NamedBeanComboBox<SignalHead> outSignalHeadComboBox = new NamedBeanComboBox<>(
165            InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME);
166    private final JLabel statusBar;
167    private final JTextField commentField;
168    private final JButton cancel;
169    private final JButton delete;
170    private final JButton apply;
171
172    // ToolTip strings
173    private final String buttonSingleTooltip = Bundle.getMessage("In_direction_of_traffic");
174    private final String buttonTrailMainTooltip = Bundle.getMessage("Signal_head_for_main_track")
175            + " " + Bundle.getMessage("through_turnout_in_either_direction");
176    private final String buttonTrailDivTooltip = Bundle.getMessage("Signal_head_for_branching_track")
177            + " " + Bundle.getMessage("through_turnout_in_either_direction");
178    private final String buttonFacingTooltip = Bundle.getMessage("Single_signal_head_on_single");
179    private final String outSignalHeadTooltip = "<html>"
180            + Bundle.getMessage("Enter_a_new_signal_head_number_or")
181            + "<br>" + Bundle.getMessage("then_hit_return_to_load_its_information.")
182            + "</html>";
183    private final String approachSensor1Tooltip = "<html>"
184            + Bundle.getMessage("Enter_sensor_that_lights_this_signal_or")
185            + "</html>";
186    private final String sensorFieldTooltip = Bundle.getMessage("Sensor_active_sets_this_signal_to_Red.");
187    private final String turnoutFieldTooltip = Bundle.getMessage("Enter_protected_turnout_number_here.");
188    private final String flashBoxTooltip = Bundle.getMessage("One_aspect_faster_than_yellow_displays")
189            + " " + Bundle.getMessage("flashing_yellow_rather_than_green");
190    private final String limitBoxTooltip = Bundle.getMessage("Limits_the_fastest_aspect_displayed")
191            + " " + Bundle.getMessage("to_yellow_rather_than_green");
192    private final String restrictingBoxTooltip = Bundle.getMessage("Limits_the_fastest_aspect_displayed")
193            + " " + Bundle.getMessage("to_flashingred_rather_than_green");
194    private final String nextSignalFieldTooltip = Bundle.getMessage("Enter_the_low_speed_signal_head_for_this_track.")
195            + " " + Bundle.getMessage("For_dual_head_signals_the_fastest_aspect_is_protected.");
196    private final String highSignalFieldTooltip = Bundle.getMessage("Enter_the_high_speed_signal_head_for_this_track.")
197            + " " + Bundle.getMessage("For_dual_head_signals_the_fastest_aspect_is_protected.");
198    private final String distantBoxTooltip = Bundle.getMessage("Mirrors_the_protected_(following)_signals_status")
199            + " " + Bundle.getMessage("unless_over_ridden_by_an_intermediate_stop_sensor.");
200
201    private final transient BlockBossLogicProvider blockBossLogicProvider;
202
203    /**
204     * Ctor for default SSL edit frame.
205     */
206    public BlockBossFrame() {
207        this(Bundle.getMessage(SIMPLE_SIGNAL_LOGIC));
208    }
209
210    /**
211     * Ctor for named SSL edit frame.
212     *
213     * @param frameName the name to use for this frame
214     */
215    private BlockBossFrame(String frameName) {
216
217        // create the frame
218        super(frameName, false, true);
219
220        blockBossLogicProvider = InstanceManager.getDefault(BlockBossLogicProvider.class);
221
222        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
223
224        // add save menu item
225        JMenuBar menuBar = new JMenuBar();
226        JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile"));
227        menuBar.add(fileMenu);
228        fileMenu.add(new jmri.configurexml.StoreMenu());
229        setJMenuBar(menuBar);
230        addHelpMenu("package.jmri.jmrit.blockboss.BlockBossFrame", true);
231
232        // create GUI items
233        sLimitBox = new JCheckBox(Bundle.getMessage(LIMITED_SPEED));
234        sRestrictingBox = new JCheckBox(Bundle.getMessage(RESTRICTING_SPEED));
235        tmLimitBox = new JCheckBox(Bundle.getMessage(LIMITED_SPEED));
236        tmLimitBox.setModel(sLimitBox.getModel());
237        tmRestrictingBox = new JCheckBox(Bundle.getMessage(RESTRICTING_SPEED));
238        tmRestrictingBox.setModel(sRestrictingBox.getModel());
239        fmLimitBox = new JCheckBox(Bundle.getMessage(LIMITED_SPEED));
240        fmLimitBox.setModel(sLimitBox.getModel());
241        fmRestrictingBox = new JCheckBox(Bundle.getMessage(RESTRICTING_SPEED));
242        fmRestrictingBox.setModel(sRestrictingBox.getModel());
243
244        tdLimitBox = new JCheckBox(Bundle.getMessage(LIMITED_SPEED));
245        tdRestrictingBox = new JCheckBox(Bundle.getMessage(RESTRICTING_SPEED));
246        fdLimitBox = new JCheckBox(Bundle.getMessage(LIMITED_SPEED));
247        fdLimitBox.setModel(tdLimitBox.getModel());
248        fdRestrictingBox = new JCheckBox(Bundle.getMessage(RESTRICTING_SPEED));
249        fdRestrictingBox.setModel(tdRestrictingBox.getModel());
250
251        sFlashBox = new JCheckBox(Bundle.getMessage(WITH_FLASHING_YELLOW));
252        tmFlashBox = new JCheckBox(Bundle.getMessage(WITH_FLASHING_YELLOW));
253        tmFlashBox.setModel(sFlashBox.getModel());
254        tdFlashBox = new JCheckBox(Bundle.getMessage(WITH_FLASHING_YELLOW));
255        tdFlashBox.setModel(sFlashBox.getModel());
256        fFlashBox = new JCheckBox(Bundle.getMessage(WITH_FLASHING_YELLOW));
257        fFlashBox.setModel(sFlashBox.getModel());
258
259        sDistantBox = new JCheckBox(Bundle.getMessage(IS_DISTANT_SIGNAL));
260        tmDistantBox = new JCheckBox(Bundle.getMessage(IS_DISTANT_SIGNAL));
261        tmDistantBox.setModel(sDistantBox.getModel());
262        tdDistantBox = new JCheckBox(Bundle.getMessage(IS_DISTANT_SIGNAL));
263        tdDistantBox.setModel(sDistantBox.getModel());
264        fDistantBox = new JCheckBox(Bundle.getMessage(IS_DISTANT_SIGNAL));
265        fDistantBox.setModel(sDistantBox.getModel());
266
267        buttonSingle = new JRadioButton(Bundle.getMessage("On_Single_Block"));
268        buttonTrailMain = new JRadioButton(Bundle.getMessage("Main_Leg_of_Turnout"));
269        buttonTrailDiv = new JRadioButton(Bundle.getMessage("Diverging_Leg_of_Turnout"));
270        buttonFacing = new JRadioButton(Bundle.getMessage("On_Facing-Point_Turnout"));
271        ButtonGroup g = new ButtonGroup();
272        g.add(buttonSingle);
273        g.add(buttonTrailMain);
274        g.add(buttonTrailDiv);
275        g.add(buttonFacing);
276        ActionListener a = e -> buttonClicked();
277
278        buttonSingle.addActionListener(a);
279        buttonTrailMain.addActionListener(a);
280        buttonTrailDiv.addActionListener(a);
281        buttonFacing.addActionListener(a);
282
283        // share sensor data models
284        tmSensorComboBox1.setModel(sSensorComboBox1.getModel());
285        tdSensorComboBox1.setModel(sSensorComboBox1.getModel());
286        fSensorComboBox1.setModel(sSensorComboBox1.getModel());
287
288        tmSensorComboBox2.setModel(sSensorComboBox2.getModel());
289        tdSensorComboBox2.setModel(sSensorComboBox2.getModel());
290        fSensorComboBox2.setModel(sSensorComboBox2.getModel());
291
292        tmSensorComboBox3.setModel(sSensorComboBox3.getModel());
293        tdSensorComboBox3.setModel(sSensorComboBox3.getModel());
294        fSensorComboBox3.setModel(sSensorComboBox3.getModel());
295
296        tmSensorComboBox4.setModel(sSensorComboBox4.getModel());
297        tdSensorComboBox4.setModel(sSensorComboBox4.getModel());
298        fSensorComboBox4.setModel(sSensorComboBox4.getModel());
299
300        tmSensorComboBox5.setModel(sSensorComboBox5.getModel());
301        tdSensorComboBox5.setModel(sSensorComboBox5.getModel());
302        fSensorComboBox5.setModel(sSensorComboBox5.getModel());
303        // share turnout data model
304        tmProtectTurnoutComboBox.setModel(tdProtectTurnoutComboBox.getModel());
305        fProtectTurnoutComboBox.setModel(tdProtectTurnoutComboBox.getModel());
306
307        tdNextSignalComboBox1.setModel(sNextSignalComboBox1.getModel());
308        tdNextSignalComboBox1Alt.setModel(sNextSignalComboBox1Alt.getModel());
309        tmNextSignalComboBox1.setModel(sNextSignalComboBox1.getModel());
310        tmNextSignalComboBox1Alt.setModel(sNextSignalComboBox1Alt.getModel());
311        fNextSignalComboBox1.setModel(sNextSignalComboBox1.getModel());
312        fNextSignalComboBox1Alt.setModel(sNextSignalComboBox1Alt.getModel());
313
314        // configure sensor combobox options
315        setupComboBox(sSensorComboBox1, false, true, true);
316        setupComboBox(sSensorComboBox2, false, true, true);
317        setupComboBox(sSensorComboBox3, false, true, true);
318        setupComboBox(sSensorComboBox4, false, true, true);
319        setupComboBox(sSensorComboBox5, false, true, true);
320        setupComboBox(tmSensorComboBox1, false, true, true);
321        setupComboBox(tmSensorComboBox2, false, true, true);
322        setupComboBox(tmSensorComboBox3, false, true, true);
323        setupComboBox(tmSensorComboBox4, false, true, true);
324        setupComboBox(tmSensorComboBox5, false, true, true);
325        setupComboBox(tdSensorComboBox1, false, true, true);
326        setupComboBox(tdSensorComboBox2, false, true, true);
327        setupComboBox(tdSensorComboBox3, false, true, true);
328        setupComboBox(tdSensorComboBox4, false, true, true);
329        setupComboBox(tdSensorComboBox5, false, true, true);
330        setupComboBox(fSensorComboBox1, false, true, true);
331        setupComboBox(fSensorComboBox2, false, true, true);
332        setupComboBox(fSensorComboBox3, false, true, true);
333        setupComboBox(fSensorComboBox4, false, true, true);
334        setupComboBox(fSensorComboBox5, false, true, true);
335        // configure turnout combobox options
336        setupComboBox(tdProtectTurnoutComboBox, false, true, true);
337        setupComboBox(tmProtectTurnoutComboBox, false, true, true);
338        setupComboBox(fProtectTurnoutComboBox, false, true, true);
339        // configure next signal combobox options
340        setupComboBox(sNextSignalComboBox1, false, true, true);
341        setupComboBox(sNextSignalComboBox1Alt, false, true, true);
342        setupComboBox(tdNextSignalComboBox1, false, true, true);
343        setupComboBox(tdNextSignalComboBox1Alt, false, true, true);
344        setupComboBox(tmNextSignalComboBox1, false, true, true);
345        setupComboBox(tmNextSignalComboBox1Alt, false, true, true);
346        setupComboBox(fNextSignalComboBox1, false, true, true);
347        setupComboBox(fNextSignalComboBox1Alt, false, true, true);
348        setupComboBox(fNextSignalComboBox2, false, true, true);
349        setupComboBox(fNextSignalComboBox2Alt, false, true, true);
350        // configure next sensor combobox options
351        setupComboBox(fNextSensorComboBox1, false, true, true);
352        setupComboBox(fNextSensorComboBox1Alt, false, true, true);
353        setupComboBox(fNextSensorComboBox2, false, true, true);
354        setupComboBox(fNextSensorComboBox2Alt, false, true, true);
355
356        // add top part of GUI, holds signal head name to drive
357        JPanel line = new JPanel();
358        line.add(new JLabel(Bundle.getMessage("SSLHeadNamedLabel")));
359        setupComboBox(outSignalHeadComboBox, true, true, true);
360        line.add(outSignalHeadComboBox);
361        outSignalHeadComboBox.setToolTipText(outSignalHeadTooltip);
362        outSignalHeadComboBox.addActionListener(e ->
363            // user hit enter, use this name to fill in the rest of the fields
364            activate());
365
366        getContentPane().add(line);
367
368        line = new JPanel();
369        line.setLayout(new BoxLayout(line, BoxLayout.Y_AXIS));
370        buttonSingle.setToolTipText(buttonSingleTooltip);
371        line.add(buttonSingle);
372        buttonTrailMain.setToolTipText(buttonTrailMainTooltip);
373        line.add(buttonTrailMain);
374        buttonTrailDiv.setToolTipText(buttonTrailDivTooltip);
375        line.add(buttonTrailDiv);
376        buttonFacing.setToolTipText(buttonFacingTooltip);
377        line.add(buttonFacing);
378        line.setAlignmentX(0.5f);
379        getContentPane().add(line);
380
381        getContentPane().add(new JSeparator(SwingConstants.HORIZONTAL));
382
383        // fill in the specific panels for the modes
384        getContentPane().add(fillModeSingle());
385        getContentPane().add(fillModeTrailMain());
386        getContentPane().add(fillModeTrailDiv());
387        getContentPane().add(fillModeFacing());
388
389        line = new JPanel();
390        line.add(new JLabel(Bundle.getMessage("ApproachLightingSensorLabel")));
391        line.add(approachSensor1ComboBox);
392        setupComboBox(approachSensor1ComboBox, false, true, true);
393        approachSensor1ComboBox.setToolTipText(approachSensor1Tooltip);
394        line.setAlignmentX(0.5f);
395        getContentPane().add(line);
396
397        // add comment element
398        line = new JPanel();
399        line.setLayout(new FlowLayout());
400        line.add(new JLabel(Bundle.getMessage("Comment")));
401        line.add(commentField = new JTextField(30));
402        commentField.setToolTipText(Bundle.getMessage("CommentToolTip"));
403        getContentPane().add(line);
404
405        // add status bar above buttons
406        line = new JPanel();
407        line.setLayout(new FlowLayout());
408        statusBar = new JLabel(Bundle.getMessage("StatusSslStart"));
409        statusBar.setFont(statusBar.getFont().deriveFont(0.9f * commentField.getFont().getSize())); // a bit smaller
410        statusBar.setForeground(Color.gray);
411        line.add(statusBar);
412        getContentPane().add(line);
413
414        getContentPane().add(new JSeparator(SwingConstants.HORIZONTAL));
415
416        JPanel buttons = new JPanel();
417        buttons.setLayout(new FlowLayout());
418        // add OK button at bottom
419
420        delete = new JButton(Bundle.getMessage("ButtonDelete"));
421        buttons.add(delete);
422        delete.addActionListener(e -> deletePressed());
423        delete.setEnabled(false);
424
425        cancel = new JButton(Bundle.getMessage("ButtonCancel"));
426        buttons.add(cancel);
427        cancel.addActionListener(e -> cancelPressed());
428
429        apply = new JButton(Bundle.getMessage("ButtonApply"));
430        apply.setToolTipText(Bundle.getMessage("ApplyToolTip"));
431        buttons.add(apply);
432        apply.setEnabled(false);
433
434        apply.addActionListener(e -> applyPressed());
435        getContentPane().add(buttons);
436
437        pack();
438        // set a definite mode selection, which also repacks.
439        buttonSingle.setSelected(true);
440        buttonClicked();
441    }
442
443    // Panel arrangements all changed to use GridBagLayout format.
444
445    private JPanel fillModeSingle() {
446        modeSingle.setLayout(new GridBagLayout());
447
448        GridBagConstraints constraints = new GridBagConstraints();
449        constraints.anchor = GridBagConstraints.EAST;
450        constraints.gridheight = 1;
451        constraints.gridwidth = 1;
452        constraints.ipadx = 0;
453        constraints.ipady = 0;
454        Insets insets = new Insets(2, 3, 2, 3); // top, left, bottom, right
455        constraints.insets = insets;
456        constraints.weightx = 1;
457        constraints.weighty = 1;
458
459        constraints.fill = GridBagConstraints.NONE;
460        constraints.gridx = 0;
461        constraints.gridy = 0;
462        insets.top = 9;
463        insets.bottom = 9;
464
465        modeSingle.add(new JLabel(Bundle.getMessage(PROTECTS_SENSOR)), constraints);
466        constraints.fill = GridBagConstraints.HORIZONTAL;
467        constraints.gridx = 1;
468        sSensorComboBox1.setToolTipText(sensorFieldTooltip);
469        modeSingle.add(sSensorComboBox1, constraints);
470        constraints.gridx = 2;
471        sSensorComboBox2.setToolTipText(sensorFieldTooltip);
472        modeSingle.add(sSensorComboBox2, constraints);
473        constraints.gridx = 3;
474        sSensorComboBox3.setToolTipText(sensorFieldTooltip);
475        modeSingle.add(sSensorComboBox3, constraints);
476        constraints.gridx = 4;
477        sSensorComboBox4.setToolTipText(sensorFieldTooltip);
478        modeSingle.add(sSensorComboBox4, constraints);
479        constraints.gridx = 5;
480        sSensorComboBox5.setToolTipText(sensorFieldTooltip);
481        modeSingle.add(sSensorComboBox5, constraints);
482
483        insets.top = 2;
484        constraints.gridx = 0;
485        constraints.gridy = 1;
486        constraints.fill = GridBagConstraints.NONE;
487
488        modeSingle.add(new JLabel(Bundle.getMessage(PROTECTS_SIGNAL)), constraints);
489        constraints.fill = GridBagConstraints.HORIZONTAL;
490        constraints.gridx = 1;
491        sNextSignalComboBox1.setToolTipText(highSignalFieldTooltip);
492        modeSingle.add(sNextSignalComboBox1, constraints);
493        constraints.gridx = 2;
494        sNextSignalComboBox1Alt.setToolTipText(nextSignalFieldTooltip);
495        modeSingle.add(sNextSignalComboBox1Alt, constraints);
496        constraints.gridx = 3;
497        constraints.gridwidth = 2;
498        // ??
499        JPanel q = new JPanel();
500        q.setLayout(new FlowLayout());
501        q.add(sLimitBox);
502        q.add(sRestrictingBox);
503        sLimitBox.setToolTipText(limitBoxTooltip);
504        sRestrictingBox.setToolTipText(restrictingBoxTooltip);
505        modeSingle.add(q, constraints);
506
507        constraints.gridy = 6;
508        constraints.gridx = 1;
509        constraints.gridwidth = 2;
510        constraints.anchor = GridBagConstraints.WEST;
511        insets.bottom = 9;
512        sFlashBox.setToolTipText(flashBoxTooltip);
513        modeSingle.add(sFlashBox, constraints);
514
515        constraints.gridx = 3;
516        sDistantBox.setToolTipText(distantBoxTooltip);
517        modeSingle.add(sDistantBox, constraints);
518        return modeSingle;
519    }
520
521    private JPanel fillModeTrailMain() {
522        modeTrailMain.setLayout(new GridBagLayout());
523
524        GridBagConstraints constraints = new GridBagConstraints();
525        constraints.anchor = GridBagConstraints.EAST;
526        constraints.gridheight = 1;
527        constraints.gridwidth = 1;
528        constraints.ipadx = 0;
529        constraints.ipady = 0;
530        Insets insets = new Insets(2, 3, 2, 3); // top, left, bottom, right
531        constraints.insets = insets;
532        constraints.weightx = 1;
533        constraints.weighty = 1;
534
535        constraints.fill = GridBagConstraints.NONE;
536        constraints.gridx = 0;
537        constraints.gridy = 0;
538        insets.top = 9;
539        insets.bottom = 9;
540        modeTrailMain.add(new JLabel(Bundle.getMessage(PROTECTS_SENSOR)), constraints);
541        constraints.fill = GridBagConstraints.HORIZONTAL;
542        constraints.gridx = 1;
543        tmSensorComboBox1.setToolTipText(sensorFieldTooltip);
544        modeTrailMain.add(tmSensorComboBox1, constraints);
545        constraints.gridx = 2;
546        tmSensorComboBox2.setToolTipText(sensorFieldTooltip);
547        modeTrailMain.add(tmSensorComboBox2, constraints);
548        constraints.gridx = 3;
549        tmSensorComboBox3.setToolTipText(sensorFieldTooltip);
550        modeTrailMain.add(tmSensorComboBox3, constraints);
551        constraints.gridx = 4;
552        tmSensorComboBox4.setToolTipText(sensorFieldTooltip);
553        modeTrailMain.add(tmSensorComboBox4, constraints);
554        constraints.gridx = 5;
555        tmSensorComboBox5.setToolTipText(sensorFieldTooltip);
556        modeTrailMain.add(tmSensorComboBox5, constraints);
557
558        insets.top = 2;
559        constraints.fill = GridBagConstraints.NONE;
560        constraints.gridx = 0;
561        constraints.gridy = 1;
562        insets.bottom = 9;
563        modeTrailMain.add(new JLabel(Bundle.getMessage("Red_When_Turnout")), constraints);
564        constraints.fill = GridBagConstraints.HORIZONTAL;
565        constraints.gridx = 1;
566        tmProtectTurnoutComboBox.setToolTipText(turnoutFieldTooltip);
567        modeTrailMain.add(tmProtectTurnoutComboBox, constraints);
568        constraints.gridx = 2;
569        constraints.gridwidth = 2;
570        modeTrailMain.add(new JLabel(Bundle.getMessage("IsState", InstanceManager.turnoutManagerInstance().getThrownText())), constraints);
571        constraints.gridwidth = 1;
572
573        constraints.fill = GridBagConstraints.NONE;
574        constraints.gridx = 0;
575        constraints.gridy = 4;
576        insets.bottom = 2;
577        modeTrailMain.add(new JLabel(Bundle.getMessage(PROTECTS_SIGNAL)), constraints);
578        constraints.fill = GridBagConstraints.HORIZONTAL;
579        constraints.gridx = 1;
580        tmNextSignalComboBox1.setToolTipText(highSignalFieldTooltip);
581        modeTrailMain.add(tmNextSignalComboBox1, constraints);
582        constraints.gridx = 2;
583        tmNextSignalComboBox1Alt.setToolTipText(nextSignalFieldTooltip);
584        modeTrailMain.add(tmNextSignalComboBox1Alt, constraints);
585        constraints.gridx = 3;
586        constraints.gridwidth = 2;
587        // ??
588        JPanel q = new JPanel();
589        q.setLayout(new FlowLayout());
590        q.add(tmLimitBox);
591        q.add(tmRestrictingBox);
592        tmLimitBox.setToolTipText(limitBoxTooltip);
593        tmRestrictingBox.setToolTipText(restrictingBoxTooltip);
594        modeTrailMain.add(q, constraints);
595
596        constraints.gridy = 6;
597        constraints.gridx = 1;
598        constraints.gridwidth = 2;
599        constraints.anchor = GridBagConstraints.WEST;
600        insets.bottom = 9;
601        tmFlashBox.setToolTipText(flashBoxTooltip);
602        modeTrailMain.add(tmFlashBox, constraints);
603
604        constraints.gridx = 3;
605        tmDistantBox.setToolTipText(distantBoxTooltip);
606        modeTrailMain.add(tmDistantBox, constraints);
607        return modeTrailMain;
608    }
609
610    private JPanel fillModeTrailDiv() {
611        modeTrailDiv.setLayout(new GridBagLayout());
612
613        GridBagConstraints constraints = new GridBagConstraints();
614        constraints.anchor = GridBagConstraints.EAST;
615        constraints.gridheight = 1;
616        constraints.gridwidth = 1;
617        constraints.ipadx = 0;
618        constraints.ipady = 0;
619        Insets insets = new Insets(2, 3, 2, 3); // top, left, bottom, right
620        constraints.insets = insets;
621        constraints.weightx = 1;
622        constraints.weighty = 1;
623
624        constraints.fill = GridBagConstraints.NONE;
625        constraints.gridx = 0;
626        constraints.gridy = 0;
627        insets.top = 9;
628        insets.bottom = 9;
629        modeTrailDiv.add(new JLabel(Bundle.getMessage(PROTECTS_SENSOR)), constraints);
630        constraints.fill = GridBagConstraints.HORIZONTAL;
631        constraints.gridx = 1;
632        tdSensorComboBox1.setToolTipText(sensorFieldTooltip);
633        modeTrailDiv.add(tdSensorComboBox1, constraints);
634        constraints.gridx = 2;
635        tdSensorComboBox2.setToolTipText(sensorFieldTooltip);
636        modeTrailDiv.add(tdSensorComboBox2, constraints);
637        constraints.gridx = 3;
638        tdSensorComboBox3.setToolTipText(sensorFieldTooltip);
639        modeTrailDiv.add(tdSensorComboBox3, constraints);
640        constraints.gridx = 4;
641        tdSensorComboBox4.setToolTipText(sensorFieldTooltip);
642        modeTrailDiv.add(tdSensorComboBox4, constraints);
643        constraints.gridx = 5;
644        tdSensorComboBox5.setToolTipText(sensorFieldTooltip);
645        modeTrailDiv.add(tdSensorComboBox5, constraints);
646
647        insets.top = 2;
648        constraints.fill = GridBagConstraints.NONE;
649        constraints.gridx = 0;
650        constraints.gridy = 1;
651        insets.bottom = 9;
652        modeTrailDiv.add(new JLabel(Bundle.getMessage("Red_When_Turnout")), constraints);
653        constraints.fill = GridBagConstraints.HORIZONTAL;
654        constraints.gridx = 1;
655        tdProtectTurnoutComboBox.setToolTipText(turnoutFieldTooltip);
656        modeTrailDiv.add(tdProtectTurnoutComboBox, constraints);
657        constraints.gridx = 2;
658        constraints.gridwidth = 2;
659        modeTrailDiv.add(new JLabel(Bundle.getMessage("IsState", InstanceManager.turnoutManagerInstance().getClosedText())), constraints);
660        constraints.gridwidth = 1;
661
662        constraints.fill = GridBagConstraints.NONE;
663        constraints.gridx = 0;
664        constraints.gridy = 4;
665        insets.bottom = 2;
666        modeTrailDiv.add(new JLabel(Bundle.getMessage(PROTECTS_SIGNAL)), constraints);
667        constraints.fill = GridBagConstraints.HORIZONTAL;
668        constraints.gridx = 1;
669        tdNextSignalComboBox1.setToolTipText(highSignalFieldTooltip);
670        modeTrailDiv.add(tdNextSignalComboBox1, constraints);
671        constraints.gridx = 2;
672        tdNextSignalComboBox1Alt.setToolTipText(nextSignalFieldTooltip);
673        modeTrailDiv.add(tdNextSignalComboBox1Alt, constraints);
674        constraints.gridx = 3;
675        constraints.gridwidth = 2;
676        // ??
677        JPanel q = new JPanel();
678        q.setLayout(new FlowLayout());
679        q.add(tdLimitBox);
680        q.add(tdRestrictingBox);
681        tdLimitBox.setToolTipText(limitBoxTooltip);
682        tdRestrictingBox.setToolTipText(restrictingBoxTooltip);
683        modeTrailDiv.add(q, constraints);
684
685        constraints.gridy = 6;
686        constraints.gridx = 1;
687        constraints.gridwidth = 2;
688        constraints.anchor = GridBagConstraints.WEST;
689        insets.bottom = 9;
690        tdFlashBox.setToolTipText(flashBoxTooltip);
691        modeTrailDiv.add(tdFlashBox, constraints);
692
693        constraints.gridx = 3;
694        tdDistantBox.setToolTipText(distantBoxTooltip);
695        modeTrailDiv.add(tdDistantBox, constraints);
696
697        return modeTrailDiv;
698    }
699
700    private JPanel fillModeFacing() {
701        modeFacing.setLayout(new GridBagLayout());
702
703        GridBagConstraints constraints = new GridBagConstraints();
704        constraints.anchor = GridBagConstraints.EAST;
705        constraints.gridheight = 1;
706        constraints.gridwidth = 1;
707        constraints.ipadx = 0;
708        constraints.ipady = 0;
709        Insets insets = new Insets(2, 3, 2, 3); // top, left, bottom, right
710        constraints.insets = insets;
711        constraints.weightx = 1;
712        constraints.weighty = 1;
713
714        constraints.fill = GridBagConstraints.NONE;
715        constraints.gridx = 0;
716        constraints.gridy = 0;
717        insets.top = 9;
718        insets.bottom = 9;
719        modeFacing.add(new JLabel(Bundle.getMessage(PROTECTS_SENSOR)), constraints);
720        constraints.fill = GridBagConstraints.HORIZONTAL;
721        constraints.gridx = 1;
722        fSensorComboBox1.setToolTipText(sensorFieldTooltip);
723        modeFacing.add(fSensorComboBox1, constraints);
724        constraints.gridx = 2;
725        fSensorComboBox2.setToolTipText(sensorFieldTooltip);
726        modeFacing.add(fSensorComboBox2, constraints);
727        constraints.gridx = 3;
728        fSensorComboBox3.setToolTipText(sensorFieldTooltip);
729        modeFacing.add(fSensorComboBox3, constraints);
730        constraints.gridx = 4;
731        fSensorComboBox4.setToolTipText(sensorFieldTooltip);
732        modeFacing.add(fSensorComboBox4, constraints);
733        constraints.gridx = 5;
734        fSensorComboBox5.setToolTipText(sensorFieldTooltip);
735        modeFacing.add(fSensorComboBox5, constraints);
736
737        insets.top = 2;
738        constraints.fill = GridBagConstraints.NONE;
739        constraints.gridx = 0;
740        constraints.gridy = 1;
741        insets.bottom = 9;
742        modeFacing.add(new JLabel(Bundle.getMessage("WatchesTurnout")), constraints);
743        constraints.fill = GridBagConstraints.HORIZONTAL;
744        constraints.gridx = 1;
745        fProtectTurnoutComboBox.setToolTipText(turnoutFieldTooltip);
746        modeFacing.add(fProtectTurnoutComboBox, constraints);
747
748        constraints.fill = GridBagConstraints.NONE;
749        constraints.gridx = 0;
750        constraints.gridy = 2;
751        insets.bottom = 2;
752        modeFacing.add(new JLabel(Bundle.getMessage("To_Protect_Signal")), constraints);
753        constraints.fill = GridBagConstraints.HORIZONTAL;
754        constraints.gridx = 1;
755        fNextSignalComboBox1.setToolTipText(highSignalFieldTooltip);
756        modeFacing.add(fNextSignalComboBox1, constraints);
757        constraints.gridx = 2;
758        fNextSignalComboBox1Alt.setToolTipText(nextSignalFieldTooltip);
759        modeFacing.add(fNextSignalComboBox1Alt, constraints);
760        constraints.gridx = 3;
761        constraints.gridwidth = 2;
762        // ??
763        JPanel q = new JPanel();
764        q.setLayout(new FlowLayout());
765        q.add(fmLimitBox);
766        q.add(fmRestrictingBox);
767        fmLimitBox.setToolTipText(limitBoxTooltip);
768        fmRestrictingBox.setToolTipText(restrictingBoxTooltip);
769        modeFacing.add(q, constraints);
770
771        constraints.fill = GridBagConstraints.NONE;
772        constraints.gridwidth = 1;
773        constraints.gridx = 0;
774        constraints.gridy = 3;
775        insets.bottom = 9;
776        modeFacing.add(new JLabel(Bundle.getMessage("And_Sensors")), constraints);
777        constraints.fill = GridBagConstraints.HORIZONTAL;
778        constraints.gridx = 1;
779        fNextSensorComboBox1.setToolTipText(sensorFieldTooltip);
780        modeFacing.add(fNextSensorComboBox1, constraints);
781        constraints.gridx = 2;
782        fNextSensorComboBox1Alt.setToolTipText(sensorFieldTooltip);
783        modeFacing.add(fNextSensorComboBox1Alt, constraints);
784        constraints.gridx = 3;
785        constraints.gridwidth = 2;
786        modeFacing.add(new JLabel(Bundle.getMessage("WhenTurnoutIsX", InstanceManager.turnoutManagerInstance().getClosedText())), constraints);
787        constraints.gridwidth = 1;
788
789        constraints.fill = GridBagConstraints.NONE;
790        constraints.gridx = 0;
791        constraints.gridy = 4;
792        insets.bottom = 2;
793        modeFacing.add(new JLabel(Bundle.getMessage("And_Protect_Signal")), constraints);
794        constraints.fill = GridBagConstraints.HORIZONTAL;
795        constraints.gridx = 1;
796        fNextSignalComboBox2.setToolTipText(highSignalFieldTooltip);
797        modeFacing.add(fNextSignalComboBox2, constraints);
798        constraints.gridx = 2;
799        fNextSignalComboBox2Alt.setToolTipText(nextSignalFieldTooltip);
800        modeFacing.add(fNextSignalComboBox2Alt, constraints);
801        constraints.gridx = 3;
802        constraints.gridwidth = 2;
803
804        q = new JPanel();
805        q.setLayout(new FlowLayout());
806        q.add(fdLimitBox);
807        q.add(fdRestrictingBox);
808        fdLimitBox.setToolTipText(limitBoxTooltip);
809        fdRestrictingBox.setToolTipText(restrictingBoxTooltip);
810        modeFacing.add(q, constraints);
811
812        constraints.fill = GridBagConstraints.NONE;
813        constraints.gridwidth = 1;
814        constraints.gridx = 0;
815        constraints.gridy = 5;
816        insets.bottom = 9;
817        modeFacing.add(new JLabel(Bundle.getMessage("And_Sensors")), constraints);
818        constraints.fill = GridBagConstraints.HORIZONTAL;
819        constraints.gridx = 1;
820        fNextSensorComboBox2.setToolTipText(sensorFieldTooltip);
821        modeFacing.add(fNextSensorComboBox2, constraints);
822        constraints.gridx = 2;
823        fNextSensorComboBox2Alt.setToolTipText(sensorFieldTooltip);
824        modeFacing.add(fNextSensorComboBox2Alt, constraints);
825        constraints.gridx = 3;
826        constraints.gridwidth = 2;
827        modeFacing.add(new JLabel(Bundle.getMessage("WhenTurnoutIsX", InstanceManager.turnoutManagerInstance().getThrownText())), constraints);
828        constraints.gridwidth = 1;
829
830        constraints.gridy = 6;
831        constraints.gridx = 1;
832        constraints.gridwidth = 2;
833        constraints.anchor = GridBagConstraints.WEST;
834        insets.bottom = 9;
835        fFlashBox.setToolTipText(flashBoxTooltip);
836        modeFacing.add(fFlashBox, constraints);
837
838        constraints.gridx = 3;
839        fDistantBox.setToolTipText(distantBoxTooltip);
840        modeFacing.add(fDistantBox, constraints);
841
842        return modeFacing;
843    }
844
845    private void applyPressed() {
846        SignalHead head = sh; // temp used here for SignalHead being operated on
847
848        // check signal head selected
849        if (head == null) {
850            head = outSignalHeadComboBox.getSelectedItem();
851            statusBar.setText(Bundle.getMessage("StatusSslCreated", outSignalHeadComboBox.getSelectedItemDisplayName()));
852        } else {
853            statusBar.setText(Bundle.getMessage("StatusSslUpdated", outSignalHeadComboBox.getSelectedItemDisplayName()));
854        }
855
856        try {
857            BlockBossLogic b = BlockBossLogic.getStoppedObject(head);
858            b.setApproachSensor1(approachSensor1ComboBox.getSelectedItemDisplayName());
859            if (buttonSingle.isSelected()) {
860                loadSingle(b);
861            } else if (buttonTrailMain.isSelected()) {
862                loadTrailMain(b);
863            } else if (buttonTrailDiv.isSelected()) {
864                loadTrailDiv(b);
865            } else if (buttonFacing.isSelected()) {
866                loadFacing(b);
867            } else {
868                log.error("no SSL type radio button was selected"); // NOI18N
869                return;
870            }
871            cancel.setText(Bundle.getMessage("ButtonClose")); // when Apply has been clicked at least once, this is not Cancel
872        } catch (IllegalArgumentException e) {
873            statusBar.setText(Bundle.getMessage("ApplyErrorDialog"));
874            JmriJOptionPane.showMessageDialog(this,
875                    Bundle.getMessage("ApplyErrorDialog"),
876                    Bundle.getMessage("ErrorTitle"),
877                    JmriJOptionPane.ERROR_MESSAGE);
878        }
879    }
880
881    private void cancelPressed() {
882        // close pane
883        this.setVisible(false);
884        statusBar.setText("");
885        super.dispose();
886    }
887
888    private void deletePressed() {
889        BlockBossLogic b = BlockBossLogic.getStoppedObject(outSignalHeadComboBox.getSelectedItemDisplayName());
890        blockBossLogicProvider.remove(b);
891        statusBar.setText(Bundle.getMessage("StatusSslDeleted", outSignalHeadComboBox.getSelectedItemDisplayName()));
892        outSignalHeadComboBox.setSelectedIndex(-1);
893        clearFields();
894    }
895
896    private void loadSingle(BlockBossLogic b) {
897        b.setSensor1(sSensorComboBox1.getSelectedItemDisplayName());
898        b.setSensor2(sSensorComboBox2.getSelectedItemDisplayName());
899        b.setSensor3(sSensorComboBox3.getSelectedItemDisplayName());
900        b.setSensor4(sSensorComboBox4.getSelectedItemDisplayName());
901        b.setSensor5(sSensorComboBox5.getSelectedItemDisplayName());
902        b.setMode(BlockBossLogic.SINGLEBLOCK);
903
904        b.setWatchedSignal1(sNextSignalComboBox1.getSelectedItemDisplayName(), sFlashBox.isSelected());
905        b.setWatchedSignal1Alt(sNextSignalComboBox1Alt.getSelectedItemDisplayName());
906        b.setLimitSpeed1(sLimitBox.isSelected());
907        b.setRestrictingSpeed1(sRestrictingBox.isSelected());
908        b.setDistantSignal(sDistantBox.isSelected());
909
910        b.setComment(commentField.getText());
911
912        blockBossLogicProvider.register(b);
913        b.start();
914    }
915
916    private void loadTrailMain(BlockBossLogic b) {
917        b.setSensor1(tmSensorComboBox1.getSelectedItemDisplayName());
918        b.setSensor2(tmSensorComboBox2.getSelectedItemDisplayName());
919        b.setSensor3(tmSensorComboBox3.getSelectedItemDisplayName());
920        b.setSensor4(tmSensorComboBox4.getSelectedItemDisplayName());
921        b.setSensor5(tmSensorComboBox5.getSelectedItemDisplayName());
922        b.setMode(BlockBossLogic.TRAILINGMAIN);
923
924        b.setTurnout(tmProtectTurnoutComboBox.getSelectedItemDisplayName());
925
926        b.setWatchedSignal1(tmNextSignalComboBox1.getSelectedItemDisplayName(), tmFlashBox.isSelected());
927        b.setWatchedSignal1Alt(tmNextSignalComboBox1Alt.getSelectedItemDisplayName());
928        b.setLimitSpeed1(tmLimitBox.isSelected());
929        b.setRestrictingSpeed1(tmRestrictingBox.isSelected());
930        b.setDistantSignal(tmDistantBox.isSelected());
931
932        b.setComment(commentField.getText());
933
934        blockBossLogicProvider.register(b);
935        b.start();
936    }
937
938    private void loadTrailDiv(BlockBossLogic b) {
939        b.setSensor1(tdSensorComboBox1.getSelectedItemDisplayName());
940        b.setSensor2(tdSensorComboBox2.getSelectedItemDisplayName());
941        b.setSensor3(tdSensorComboBox3.getSelectedItemDisplayName());
942        b.setSensor4(tdSensorComboBox4.getSelectedItemDisplayName());
943        b.setSensor5(tdSensorComboBox5.getSelectedItemDisplayName());
944        b.setMode(BlockBossLogic.TRAILINGDIVERGING);
945
946        b.setTurnout(tdProtectTurnoutComboBox.getSelectedItemDisplayName());
947
948        b.setWatchedSignal1(tdNextSignalComboBox1.getSelectedItemDisplayName(), tdFlashBox.isSelected());
949        b.setWatchedSignal1Alt(tdNextSignalComboBox1Alt.getSelectedItemDisplayName());
950        b.setLimitSpeed2(tdLimitBox.isSelected());
951        b.setRestrictingSpeed1(tdRestrictingBox.isSelected());
952        b.setDistantSignal(tdDistantBox.isSelected());
953
954        b.setComment(commentField.getText());
955
956        blockBossLogicProvider.register(b);
957        b.start();
958    }
959
960    private void loadFacing(BlockBossLogic b) {
961        b.setSensor1(fSensorComboBox1.getSelectedItemDisplayName());
962        b.setSensor2(fSensorComboBox2.getSelectedItemDisplayName());
963        b.setSensor3(fSensorComboBox3.getSelectedItemDisplayName());
964        b.setSensor4(fSensorComboBox4.getSelectedItemDisplayName());
965        b.setSensor5(fSensorComboBox5.getSelectedItemDisplayName());
966        b.setMode(BlockBossLogic.FACING);
967
968        b.setTurnout(fProtectTurnoutComboBox.getSelectedItemDisplayName());
969
970        b.setWatchedSignal1(fNextSignalComboBox1.getSelectedItemDisplayName(), fFlashBox.isSelected());
971        b.setWatchedSignal1Alt(fNextSignalComboBox1Alt.getSelectedItemDisplayName());
972        b.setWatchedSignal2(fNextSignalComboBox2.getSelectedItemDisplayName());
973        b.setWatchedSignal2Alt(fNextSignalComboBox2Alt.getSelectedItemDisplayName());
974        b.setWatchedSensor1(fNextSensorComboBox1.getSelectedItemDisplayName());
975        b.setWatchedSensor1Alt(fNextSensorComboBox1Alt.getSelectedItemDisplayName());
976        b.setWatchedSensor2(fNextSensorComboBox2.getSelectedItemDisplayName());
977        b.setWatchedSensor2Alt(fNextSensorComboBox2Alt.getSelectedItemDisplayName());
978        b.setLimitSpeed1(fmLimitBox.isSelected());
979        b.setRestrictingSpeed1(fmRestrictingBox.isSelected());
980        b.setLimitSpeed2(fdLimitBox.isSelected());
981        b.setRestrictingSpeed2(fdRestrictingBox.isSelected());
982
983        b.setDistantSignal(fDistantBox.isSelected());
984
985        b.setComment(commentField.getText());
986
987        blockBossLogicProvider.register(b);
988        b.start();
989    }
990
991    private void clearFields() {
992        approachSensor1ComboBox.setSelectedIndex(-1);
993
994        sSensorComboBox1.setSelectedIndex(-1);
995        sSensorComboBox2.setSelectedIndex(-1);
996        sSensorComboBox3.setSelectedIndex(-1);
997        sSensorComboBox4.setSelectedIndex(-1);
998        sSensorComboBox5.setSelectedIndex(-1);
999
1000        tmProtectTurnoutComboBox.setSelectedIndex(-1);
1001
1002        sNextSignalComboBox1.setSelectedIndex(-1);
1003        sNextSignalComboBox1Alt.setSelectedIndex(-1);
1004
1005        fNextSignalComboBox2.setSelectedIndex(-1);
1006        fNextSignalComboBox2Alt.setSelectedIndex(-1);
1007
1008        fNextSensorComboBox1.setSelectedIndex(-1);
1009        fNextSensorComboBox1Alt.setSelectedIndex(-1);
1010        fNextSensorComboBox2.setSelectedIndex(-1);
1011        fNextSensorComboBox2Alt.setSelectedIndex(-1);
1012
1013        sLimitBox.setSelected(false);
1014        sRestrictingBox.setSelected(false);
1015        tdLimitBox.setSelected(false);
1016        tdRestrictingBox.setSelected(false);
1017        sFlashBox.setSelected(false);
1018        sDistantBox.setSelected(false);
1019
1020        commentField.setText("");
1021
1022        buttonClicked();
1023    }
1024
1025    private void activate() {
1026        // check signal head exists
1027        if (sh == null && outSignalHeadComboBox.getSelectedItem() == null) {
1028            // head not exist, just title the window and leave
1029            setTitle(Bundle.getMessage(SIMPLE_SIGNAL_LOGIC));
1030            apply.setEnabled(false);
1031            delete.setEnabled(false);
1032            return;
1033        }
1034
1035        // find existing logic
1036        BlockBossLogic b;
1037        if (sh != null) {
1038            b = blockBossLogicProvider.provide(sh);
1039        } else {
1040            b = blockBossLogicProvider.provide(outSignalHeadComboBox.getSelectedItem());
1041        }
1042        apply.setEnabled(true);
1043        delete.setEnabled(true);
1044
1045        setTitle(Bundle.getMessage("SignalLogicForX", outSignalHeadComboBox.getSelectedItemDisplayName()));
1046
1047        approachSensor1ComboBox.setSelectedItemByName(b.getApproachSensor1());
1048
1049        sSensorComboBox1.setSelectedItemByName(b.getSensor1());
1050        sSensorComboBox2.setSelectedItemByName(b.getSensor2());
1051        sSensorComboBox3.setSelectedItemByName(b.getSensor3());
1052        sSensorComboBox4.setSelectedItemByName(b.getSensor4());
1053        sSensorComboBox5.setSelectedItemByName(b.getSensor5());
1054
1055        tmProtectTurnoutComboBox.setSelectedItemByName(b.getTurnout());
1056
1057        sNextSignalComboBox1.setSelectedItemByName(b.getWatchedSignal1());
1058        sNextSignalComboBox1Alt.setSelectedItemByName(b.getWatchedSignal1Alt());
1059
1060        fNextSignalComboBox2.setSelectedItemByName(b.getWatchedSignal2());
1061        fNextSignalComboBox2Alt.setSelectedItemByName(b.getWatchedSignal2Alt());
1062
1063        fNextSensorComboBox1.setSelectedItemByName(b.getWatchedSensor1());
1064        fNextSensorComboBox1Alt.setSelectedItemByName(b.getWatchedSensor1Alt());
1065        fNextSensorComboBox2.setSelectedItemByName(b.getWatchedSensor2());
1066        fNextSensorComboBox2Alt.setSelectedItemByName(b.getWatchedSensor2Alt());
1067
1068        sLimitBox.setSelected(b.getLimitSpeed1());
1069        sRestrictingBox.setSelected(b.getRestrictingSpeed1());
1070        tdLimitBox.setSelected(b.getLimitSpeed2());
1071        tdRestrictingBox.setSelected(b.getRestrictingSpeed2());
1072        sFlashBox.setSelected(b.getUseFlash());
1073        sDistantBox.setSelected(b.getDistantSignal());
1074
1075        commentField.setText(b.getComment());
1076
1077        int mode = b.getMode();
1078        if (mode == BlockBossLogic.SINGLEBLOCK) {
1079            buttonSingle.setSelected(true);
1080        } else if (mode == BlockBossLogic.TRAILINGMAIN) {
1081            buttonTrailMain.setSelected(true);
1082        } else if (mode == BlockBossLogic.TRAILINGDIVERGING) {
1083            buttonTrailDiv.setSelected(true);
1084        } else if (mode == BlockBossLogic.FACING) {
1085            buttonFacing.setSelected(true);
1086        }
1087
1088        statusBar.setText(Bundle.getMessage("StatusSslLoaded", Bundle.getMessage("ButtonApply")));
1089        // do setup of visible panels
1090        buttonClicked();
1091    }
1092
1093    private void buttonClicked() {
1094        modeSingle.setVisible(false);
1095        modeTrailMain.setVisible(false);
1096        modeTrailDiv.setVisible(false);
1097        modeFacing.setVisible(false);
1098        if (buttonSingle.isSelected()) {
1099            modeSingle.setVisible(true);
1100        } else if (buttonTrailMain.isSelected()) {
1101            modeTrailMain.setVisible(true);
1102        } else if (buttonTrailDiv.isSelected()) {
1103            modeTrailDiv.setVisible(true);
1104        } else if (buttonFacing.isSelected()) {
1105            modeFacing.setVisible(true);
1106        } else {
1107            log.debug("buttonClicked(): no SSL type radio button was selected");
1108        }
1109        modeSingle.revalidate();
1110        modeTrailMain.revalidate();
1111        modeTrailDiv.revalidate();
1112        modeFacing.revalidate();
1113        pack();
1114        modeSingle.repaint();
1115        modeTrailMain.repaint();
1116        modeTrailDiv.repaint();
1117        modeFacing.repaint();
1118    }
1119
1120    private SignalHead sh = null;
1121
1122    /**
1123     * Programmatically open the frame to edit a specific SSL by signal head.
1124     *
1125     * @param sh signal head of which the name should be entered in the Edit pane
1126     */
1127    public void setSignal(SignalHead sh) {
1128        this.sh = sh;
1129        outSignalHeadComboBox.setSelectedItem(sh);
1130        outSignalHeadComboBox.setEnabled(false);
1131        activate();
1132    }
1133
1134    /**
1135     * Programmatically open the frame to edit a specific SSL by signal head system name.
1136     *
1137     * @param name system or user name of the signal head to be entered in the Edit pane
1138     */
1139    public void setSignal(String name) {
1140        sh = null;
1141        outSignalHeadComboBox.setSelectedItemByName(name);
1142        outSignalHeadComboBox.setEnabled(true);
1143        activate();
1144    }
1145
1146    /**
1147     * Set up editable NamedBeanComboBoxes for SSL pane.
1148     * Copied from LayoutEditor
1149     * @see jmri.jmrit.display.layoutEditor.LayoutEditor#setupComboBox(NamedBeanComboBox, boolean, boolean, boolean)
1150     * @author G. Warner 2017
1151     *
1152     * @param inComboBox     the editable NamedBeanComboBoxes to set up
1153     * @param inValidateMode boolean: if true, typed in text is validated; if
1154     *                       false input text is not
1155     * @param inEnable       boolean to enable / disable the NamedBeanComboBox
1156     * @param inFirstBlank   boolean to enable / disable the first item being
1157     *                       blank
1158     */
1159    private static void setupComboBox(@Nonnull NamedBeanComboBox<?> inComboBox, boolean inValidateMode, boolean inEnable, boolean inFirstBlank) {
1160        log.debug("SSL setupComboBox called");
1161        inComboBox.setEnabled(inEnable);
1162        inComboBox.setEditable(false);
1163        inComboBox.setValidatingInput(inValidateMode);
1164        inComboBox.setSelectedItem(null);
1165        inComboBox.setAllowNull(inFirstBlank);
1166        jmri.util.swing.JComboBoxUtil.setupComboBoxMaxRows(inComboBox);
1167        inComboBox.setSelectedIndex(-1);
1168    }
1169
1170    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BlockBossFrame.class);
1171
1172}