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