001package jmri.jmrit.ctc.editor.gui;
002
003import jmri.jmrit.ctc.editor.code.AwtWindowProperties;
004import jmri.jmrit.ctc.editor.code.CheckJMRIObject;
005import jmri.jmrit.ctc.editor.code.CodeButtonHandlerDataRoutines;
006import jmri.jmrit.ctc.editor.code.CommonSubs;
007import jmri.jmrit.ctc.editor.code.ProgramProperties;
008
009import java.util.ArrayList;
010import java.util.HashSet;
011
012import javax.swing.JComboBox;
013
014import jmri.InstanceManager;
015import jmri.TurnoutManager;
016import jmri.jmrit.ctc.NBHTurnout;
017import jmri.jmrit.ctc.ctcserialdata.*;
018
019/**
020 *
021 * @author Gregory J. Bedlek Copyright (C) 2018, 2019
022 *
023 * 7/30/2020 Bug Fix (found by a user in the field, as reported to Dave Sand):
024 * The user can in two different O.S. sections (or in the
025 * same O.S. section) mention the same turnout multiple times.  Now, of course
026 * this is illegal, however the program does NOT (at present) enforce this.
027 * Then at run-time, this causes an "infinite loop" as each tries to fight
028 * against the other(s), and eventually the stack overflows.
029 * To Fix: At start of form, get a list of all other O.S. sections turnouts
030 * that are mentioned, this is a "static" exclusion list for this time only
031 * run" of this form.
032 * In addition, when editing one of the lists, the other 3 lists selected
033 * items also are excluded "dynamically".
034 */
035public class FrmTUL extends javax.swing.JFrame {
036
037    /**
038     * Creates new form DlgTUL
039     */
040    private static final String FORM_PROPERTIES = "DlgTUL";     // NOI18N
041    private static final String PREFIX = "_mTUL_";              // NOI18N
042    private final AwtWindowProperties _mAwtWindowProperties;
043    private final CTCSerialData _mCTCSerialData;
044    private boolean _mClosedNormally = false;
045    public boolean closedNormally() { return _mClosedNormally; }
046    private final CodeButtonHandlerData _mCodeButtonHandlerData;
047    private final ProgramProperties _mProgramProperties;
048    private final CheckJMRIObject _mCheckJMRIObject;
049
050//  For support of no dups:
051    private final HashSet<String> _mStartingHashSetOfTurnouts = new HashSet<>();
052    private final ArrayList<String> _mArrayListOfThisRecordsUsedLockedTurnouts = new ArrayList<>(); // Should "always" be 4 in length.  See "initializeAll4LockedTurnoutJComboBoxesAndSupportingData"
053    private boolean _mIgnoreActionEvent = false;
054    private String _mCurrentExternalTurnout;
055    private String _mCurrentAdditionalTurnout1;
056    private String _mCurrentAdditionalTurnout2;
057    private String _mCurrentAdditionalTurnout3;
058//  End of support of no dups.
059
060    private String _mTUL_ExternalTurnoutOrig;
061    private boolean _mTUL_ExternalTurnoutFeedbackDifferentOrig;
062    private boolean _mTUL_NoDispatcherControlOfSwitchOrig;
063    private boolean _mTUL_ndcos_WhenLockedSwitchStateIsClosedOrig;
064    private boolean _mTUL_GUI_IconsEnabledOrig;
065    private CodeButtonHandlerData.LOCK_IMPLEMENTATION _mTUL_LockImplementationOrig;
066    private String _mTUL_AdditionalExternalTurnout1Orig;
067    private boolean _mTUL_AdditionalExternalTurnout1FeedbackDifferentOrig;
068    private String _mTUL_AdditionalExternalTurnout2Orig;
069    private boolean _mTUL_AdditionalExternalTurnout2FeedbackDifferentOrig;
070    private String _mTUL_AdditionalExternalTurnout3Orig;
071    private boolean _mTUL_AdditionalExternalTurnout3FeedbackDifferentOrig;
072
073    private void initOrig() {
074        _mTUL_ExternalTurnoutOrig = _mCodeButtonHandlerData._mTUL_ExternalTurnout.getHandleName();
075        _mTUL_ExternalTurnoutFeedbackDifferentOrig = _mCodeButtonHandlerData._mTUL_ExternalTurnoutFeedbackDifferent;
076        _mTUL_NoDispatcherControlOfSwitchOrig = _mCodeButtonHandlerData._mTUL_NoDispatcherControlOfSwitch;
077        _mTUL_GUI_IconsEnabledOrig = _mCodeButtonHandlerData._mTUL_GUI_IconsEnabled;
078        _mTUL_ndcos_WhenLockedSwitchStateIsClosedOrig = _mCodeButtonHandlerData._mTUL_ndcos_WhenLockedSwitchStateIsClosed;
079        _mTUL_LockImplementationOrig = _mCodeButtonHandlerData._mTUL_LockImplementation;
080        _mTUL_AdditionalExternalTurnout1Orig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1.getHandleName();
081        _mTUL_AdditionalExternalTurnout1FeedbackDifferentOrig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1FeedbackDifferent;
082        _mTUL_AdditionalExternalTurnout2Orig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2.getHandleName();
083        _mTUL_AdditionalExternalTurnout2FeedbackDifferentOrig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2FeedbackDifferent;
084        _mTUL_AdditionalExternalTurnout3Orig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3.getHandleName();
085        _mTUL_AdditionalExternalTurnout3FeedbackDifferentOrig = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3FeedbackDifferent;
086    }
087
088    private boolean dataChanged() {
089        if (!_mTUL_ExternalTurnoutOrig.equals(_mTUL_ExternalTurnout.getSelectedItem())) return true;
090        if (_mTUL_ExternalTurnoutFeedbackDifferentOrig != _mTUL_ExternalTurnoutFeedbackDifferent.isSelected()) return true;
091        if (_mTUL_NoDispatcherControlOfSwitchOrig != _mTUL_NoDispatcherControlOfSwitch.isSelected()) return true;
092        if (_mTUL_ndcos_WhenLockedSwitchStateIsClosedOrig != _mTUL_ndcos_WhenLockedSwitchStateIsClosed.isSelected()) return true;
093        if (_mTUL_GUI_IconsEnabledOrig != _mTUL_GUI_IconsEnabled.isSelected()) return true;
094        if (_mTUL_LockImplementationOrig != CodeButtonHandlerData.LOCK_IMPLEMENTATION.getLockImplementation(_mTUL_LockImplementation)) return true;
095        if (!_mTUL_AdditionalExternalTurnout1Orig.equals(_mTUL_AdditionalExternalTurnout1.getSelectedItem())) return true;
096        if (_mTUL_AdditionalExternalTurnout1FeedbackDifferentOrig != _mTUL_AdditionalExternalTurnout1FeedbackDifferent.isSelected()) return true;
097        if (!_mTUL_AdditionalExternalTurnout2Orig.equals(_mTUL_AdditionalExternalTurnout2.getSelectedItem())) return true;
098        if (_mTUL_AdditionalExternalTurnout2FeedbackDifferentOrig != _mTUL_AdditionalExternalTurnout2FeedbackDifferent.isSelected()) return true;
099        if (!_mTUL_AdditionalExternalTurnout3Orig.equals(_mTUL_AdditionalExternalTurnout3.getSelectedItem())) return true;
100        if (_mTUL_AdditionalExternalTurnout3FeedbackDifferentOrig != _mTUL_AdditionalExternalTurnout3FeedbackDifferent.isSelected()) return true;
101        return false;
102    }
103
104    public FrmTUL(  AwtWindowProperties awtWindowProperties,
105                    CTCSerialData ctcSerialData,
106                    CodeButtonHandlerData codeButtonHandlerData,
107                    ProgramProperties programProperties, CheckJMRIObject checkJMRIObject) {
108        super();
109        initComponents();
110        CommonSubs.addHelpMenu(this, "package.jmri.jmrit.ctc.CTC_frmTUL", true);  // NOI18N
111        _mAwtWindowProperties = awtWindowProperties;
112        _mCTCSerialData = ctcSerialData;
113        _mCodeButtonHandlerData = codeButtonHandlerData;
114        _mProgramProperties = programProperties;
115        _mCheckJMRIObject = checkJMRIObject;
116        CommonSubs.numberButtonGroup(_mTUL_LockImplementation);
117        CommonSubs.setButtonSelected(_mTUL_LockImplementation, _mCodeButtonHandlerData._mTUL_LockImplementation.getInt());
118        CommonSubs.populateJComboBoxWithBeans(_mTUL_DispatcherInternalSensorLockToggle, "Sensor", _mCodeButtonHandlerData._mTUL_DispatcherInternalSensorLockToggle.getHandleName(), false);   // NOI18N
119        CommonSubs.populateJComboBoxWithBeans(_mTUL_DispatcherInternalSensorUnlockedIndicator, "Sensor", _mCodeButtonHandlerData._mTUL_DispatcherInternalSensorUnlockedIndicator.getHandleName(), false);   // NOI18N
120        _mTUL_ExternalTurnoutFeedbackDifferent.setSelected(_mCodeButtonHandlerData._mTUL_ExternalTurnoutFeedbackDifferent);
121        _mTUL_GUI_IconsEnabled.setSelected(_mCodeButtonHandlerData._mTUL_GUI_IconsEnabled);
122        _mTUL_NoDispatcherControlOfSwitch.setSelected(_mCodeButtonHandlerData._mTUL_NoDispatcherControlOfSwitch);
123        _mTUL_ndcos_WhenLockedSwitchStateIsClosed.setSelected(_mCodeButtonHandlerData._mTUL_ndcos_WhenLockedSwitchStateIsClosed);
124        _mTUL_NoDispatcherControlOfSwitchActionPerformed(null);     // Enable/Disable _mTUL_ndcos_WhenLockedSwitchStateIsClosed
125
126        // The CTCv1 import process can create empty NBHSensors.
127        if (!_mCodeButtonHandlerData._mTUL_DispatcherInternalSensorLockToggle.valid()) {
128            // Use reapply patterns to fix the sensors
129            jButton2ActionPerformed(null);
130        }
131
132        _mTUL_AdditionalExternalTurnout1FeedbackDifferent.setSelected(_mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1FeedbackDifferent);
133        _mTUL_AdditionalExternalTurnout2FeedbackDifferent.setSelected(_mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2FeedbackDifferent);
134        _mTUL_AdditionalExternalTurnout3FeedbackDifferent.setSelected(_mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3FeedbackDifferent);
135        _mCurrentExternalTurnout = _mCodeButtonHandlerData._mTUL_ExternalTurnout.getHandleName();
136        _mCurrentAdditionalTurnout1 = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1.getHandleName();
137        _mCurrentAdditionalTurnout2 = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2.getHandleName();
138        _mCurrentAdditionalTurnout3 = _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3.getHandleName();
139        initOrig();
140        initializeAll4LockedTurnoutJComboBoxesAndSupportingData();
141        _mAwtWindowProperties.setWindowState(this, FORM_PROPERTIES);
142        this.getRootPane().setDefaultButton(_mSaveAndClose);
143    }
144
145    public static boolean dialogCodeButtonHandlerDataValid(CheckJMRIObject checkJMRIObject, CodeButtonHandlerData codeButtonHandlerData) {
146        if (!codeButtonHandlerData._mTUL_Enabled) return true; // Not enabled, can be no error!
147//  Checks:
148        if (ProjectsCommonSubs.isNullOrEmptyString(codeButtonHandlerData._mTUL_ExternalTurnout.getHandleName())) return false;
149        return checkJMRIObject.validClassWithPrefix(PREFIX, codeButtonHandlerData);
150    }
151
152//  Validate all internal fields as much as possible:
153    private ArrayList<String> formFieldsValid() {
154        ArrayList<String> errors = new ArrayList<>();
155//  Checks:
156        CommonSubs.checkJComboBoxNotEmpty(_mTUL_ExternalTurnout, _mTUL_ActualTurnoutPrompt, errors);
157        _mCheckJMRIObject.analyzeForm(PREFIX, this, errors);
158        return errors;
159    }
160
161    /**
162     * This method is called from within the constructor to initialize the form.
163     * WARNING: Do NOT modify this code. The content of this method is always
164     * regenerated by the Form Editor.
165     */
166    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
167    private void initComponents() {
168
169        _mTUL_LockImplementation = new javax.swing.ButtonGroup();
170        _mSaveAndClose = new javax.swing.JButton();
171        jLabel2 = new javax.swing.JLabel();
172        _mTUL_DispatcherInternalSensorLockToggle = new javax.swing.JComboBox<>();
173        _mTUL_ExternalTurnoutFeedbackDifferent = new javax.swing.JCheckBox();
174        jLabel4 = new javax.swing.JLabel();
175        _mTUL_ActualTurnoutPrompt = new javax.swing.JLabel();
176        jLabel6 = new javax.swing.JLabel();
177        _mTUL_DispatcherInternalSensorUnlockedIndicator = new javax.swing.JComboBox<>();
178        _mTUL_NoDispatcherControlOfSwitch = new javax.swing.JCheckBox();
179        jLabel7 = new javax.swing.JLabel();
180        _mTUL_GUI_IconsEnabled = new javax.swing.JCheckBox();
181        _mLabelDlgTULGUIEnable = new javax.swing.JLabel();
182        jButton2 = new javax.swing.JButton();
183        jRadioButton1 = new javax.swing.JRadioButton();
184        jLabel1 = new javax.swing.JLabel();
185        jRadioButton2 = new javax.swing.JRadioButton();
186        jLabel11 = new javax.swing.JLabel();
187        _mTUL_AdditionalExternalTurnout1FeedbackDifferent = new javax.swing.JCheckBox();
188        _mTUL_AdditionalExternalTurnout2FeedbackDifferent = new javax.swing.JCheckBox();
189        _mTUL_AdditionalExternalTurnout3FeedbackDifferent = new javax.swing.JCheckBox();
190        _mTUL_ExternalTurnout = new javax.swing.JComboBox<>();
191        _mTUL_AdditionalExternalTurnout1 = new javax.swing.JComboBox<>();
192        _mTUL_AdditionalExternalTurnout2 = new javax.swing.JComboBox<>();
193        _mTUL_AdditionalExternalTurnout3 = new javax.swing.JComboBox<>();
194        _mLabelDlgTULClosed = new javax.swing.JLabel();
195        _mTUL_ndcos_WhenLockedSwitchStateIsClosed = new javax.swing.JCheckBox();
196
197        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
198        setTitle(Bundle.getMessage("TitleDlgTUL"));
199        addWindowListener(new java.awt.event.WindowAdapter() {
200            @Override
201            public void windowClosing(java.awt.event.WindowEvent evt) {
202                formWindowClosing(evt);
203            }
204        });
205
206        _mSaveAndClose.setText(Bundle.getMessage("ButtonSaveClose"));
207        _mSaveAndClose.addActionListener(new java.awt.event.ActionListener() {
208            @Override
209            public void actionPerformed(java.awt.event.ActionEvent evt) {
210                _mSaveAndCloseActionPerformed(evt);
211            }
212        });
213
214        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
215        jLabel2.setText(Bundle.getMessage("LabelDlgTULSensor"));
216
217        _mTUL_DispatcherInternalSensorLockToggle.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
218
219        _mTUL_ExternalTurnoutFeedbackDifferent.setText(" ");
220
221        jLabel4.setText(Bundle.getMessage("InfoDlgTULFeedback"));
222
223        _mTUL_ActualTurnoutPrompt.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
224        _mTUL_ActualTurnoutPrompt.setText(Bundle.getMessage("LabelDlgTULToName"));
225
226        jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
227        jLabel6.setText(Bundle.getMessage("LabelDlgTULInd"));
228
229        _mTUL_DispatcherInternalSensorUnlockedIndicator.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
230
231        _mTUL_NoDispatcherControlOfSwitch.setText(" ");
232        _mTUL_NoDispatcherControlOfSwitch.setToolTipText(Bundle.getMessage("TipDlgTULNoDisp"));
233        _mTUL_NoDispatcherControlOfSwitch.addActionListener(new java.awt.event.ActionListener() {
234            @Override
235            public void actionPerformed(java.awt.event.ActionEvent evt) {
236                _mTUL_NoDispatcherControlOfSwitchActionPerformed(evt);
237            }
238        });
239
240        jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
241        jLabel7.setText(Bundle.getMessage("LabelDlgTULNoDisp"));
242
243        _mTUL_GUI_IconsEnabled.setText(" ");
244        _mTUL_GUI_IconsEnabled.setToolTipText(Bundle.getMessage("TipDlgTULGUIEnable"));
245
246        _mLabelDlgTULGUIEnable.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
247        _mLabelDlgTULGUIEnable.setText(Bundle.getMessage("LabelDlgTULGUIEnable"));
248
249        jButton2.setText(Bundle.getMessage("ButtonReapply"));
250        jButton2.addActionListener(new java.awt.event.ActionListener() {
251            @Override
252            public void actionPerformed(java.awt.event.ActionEvent evt) {
253                jButton2ActionPerformed(evt);
254            }
255        });
256
257        _mTUL_LockImplementation.add(jRadioButton1);
258        jRadioButton1.setText(Bundle.getMessage("LabelDlgTULGregs"));
259
260        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
261        jLabel1.setText(Bundle.getMessage("InfoDlgTULLock"));
262
263        _mTUL_LockImplementation.add(jRadioButton2);
264        jRadioButton2.setText(Bundle.getMessage("LabelDlgTULOther"));
265        jRadioButton2.setEnabled(false);
266
267        jLabel11.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
268        jLabel11.setText(Bundle.getMessage("LabelDlgTULToOpt"));
269
270        _mTUL_AdditionalExternalTurnout1FeedbackDifferent.setText(" ");
271
272        _mTUL_AdditionalExternalTurnout2FeedbackDifferent.setText(" ");
273
274        _mTUL_AdditionalExternalTurnout3FeedbackDifferent.setText(" ");
275
276        _mTUL_ExternalTurnout.addActionListener(new java.awt.event.ActionListener() {
277            @Override
278            public void actionPerformed(java.awt.event.ActionEvent evt) {
279                _mTUL_ExternalTurnoutActionPerformed(evt);
280            }
281        });
282
283        _mTUL_AdditionalExternalTurnout1.addActionListener(new java.awt.event.ActionListener() {
284            @Override
285            public void actionPerformed(java.awt.event.ActionEvent evt) {
286                _mTUL_AdditionalExternalTurnout1ActionPerformed(evt);
287            }
288        });
289
290        _mTUL_AdditionalExternalTurnout2.addActionListener(new java.awt.event.ActionListener() {
291            @Override
292            public void actionPerformed(java.awt.event.ActionEvent evt) {
293                _mTUL_AdditionalExternalTurnout2ActionPerformed(evt);
294            }
295        });
296
297        _mTUL_AdditionalExternalTurnout3.addActionListener(new java.awt.event.ActionListener() {
298            @Override
299            public void actionPerformed(java.awt.event.ActionEvent evt) {
300                _mTUL_AdditionalExternalTurnout3ActionPerformed(evt);
301            }
302        });
303
304        _mLabelDlgTULClosed.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
305        _mLabelDlgTULClosed.setText(Bundle.getMessage("LabelDlgTULClosed"));
306
307        _mTUL_ndcos_WhenLockedSwitchStateIsClosed.setText(" ");
308        _mTUL_ndcos_WhenLockedSwitchStateIsClosed.setToolTipText(Bundle.getMessage("TipDlgTULClosed"));
309
310        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
311        getContentPane().setLayout(layout);
312        layout.setHorizontalGroup(
313            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
314            .addGroup(layout.createSequentialGroup()
315                .addGap(71, 71, 71)
316                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
317                    .addComponent(jLabel6)
318                    .addComponent(jLabel1)
319                    .addComponent(jLabel11)
320                    .addComponent(_mTUL_ActualTurnoutPrompt)
321                    .addComponent(jLabel2)
322                    .addComponent(jButton2)
323                    .addComponent(jLabel7)
324                    .addComponent(_mLabelDlgTULGUIEnable))
325                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
326                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
327                    .addGroup(layout.createSequentialGroup()
328                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
329                            .addComponent(_mTUL_AdditionalExternalTurnout3, 0, 133, Short.MAX_VALUE)
330                            .addComponent(_mTUL_AdditionalExternalTurnout2, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
331                            .addComponent(_mTUL_AdditionalExternalTurnout1, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
332                            .addComponent(_mTUL_ExternalTurnout, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
333                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
334                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
335                            .addGroup(layout.createSequentialGroup()
336                                .addComponent(_mTUL_ExternalTurnoutFeedbackDifferent)
337                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
338                                .addComponent(jLabel4))
339                            .addComponent(_mTUL_AdditionalExternalTurnout1FeedbackDifferent)
340                            .addComponent(_mTUL_AdditionalExternalTurnout2FeedbackDifferent)
341                            .addComponent(_mTUL_AdditionalExternalTurnout3FeedbackDifferent)))
342                    .addComponent(_mTUL_DispatcherInternalSensorLockToggle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
343                    .addComponent(_mTUL_DispatcherInternalSensorUnlockedIndicator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
344                    .addGroup(layout.createSequentialGroup()
345                        .addGap(57, 57, 57)
346                        .addComponent(_mSaveAndClose))
347                    .addGroup(layout.createSequentialGroup()
348                        .addComponent(_mTUL_NoDispatcherControlOfSwitch)
349                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
350                        .addComponent(_mLabelDlgTULClosed)
351                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
352                        .addComponent(_mTUL_ndcos_WhenLockedSwitchStateIsClosed))
353                    .addComponent(_mTUL_GUI_IconsEnabled)
354                    .addGroup(layout.createSequentialGroup()
355                        .addComponent(jRadioButton1)
356                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
357                        .addComponent(jRadioButton2)))
358                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
359        );
360        layout.setVerticalGroup(
361            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
362            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
363                .addContainerGap()
364                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
365                    .addComponent(jLabel2)
366                    .addComponent(_mTUL_DispatcherInternalSensorLockToggle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
367                .addGap(7, 7, 7)
368                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
369                    .addComponent(_mTUL_ActualTurnoutPrompt)
370                    .addComponent(_mTUL_ExternalTurnoutFeedbackDifferent)
371                    .addComponent(jLabel4)
372                    .addComponent(_mTUL_ExternalTurnout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
373                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
374                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
375                    .addComponent(jLabel11)
376                    .addComponent(_mTUL_AdditionalExternalTurnout1FeedbackDifferent)
377                    .addComponent(_mTUL_AdditionalExternalTurnout1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
378                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
379                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
380                    .addComponent(_mTUL_AdditionalExternalTurnout2FeedbackDifferent)
381                    .addComponent(_mTUL_AdditionalExternalTurnout2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
382                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
383                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
384                    .addComponent(_mTUL_AdditionalExternalTurnout3FeedbackDifferent)
385                    .addComponent(_mTUL_AdditionalExternalTurnout3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
386                .addGap(6, 6, 6)
387                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
388                    .addComponent(jLabel6)
389                    .addComponent(_mTUL_DispatcherInternalSensorUnlockedIndicator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
390                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
391                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
392                    .addComponent(_mTUL_GUI_IconsEnabled)
393                    .addComponent(_mLabelDlgTULGUIEnable))
394                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
395                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
396                    .addComponent(jLabel7)
397                    .addComponent(_mTUL_NoDispatcherControlOfSwitch)
398                    .addComponent(_mLabelDlgTULClosed)
399                    .addComponent(_mTUL_ndcos_WhenLockedSwitchStateIsClosed))
400                .addGap(18, 18, 18)
401                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
402                    .addComponent(jLabel1)
403                    .addComponent(jRadioButton1)
404                    .addComponent(jRadioButton2))
405                .addGap(18, 18, Short.MAX_VALUE)
406                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
407                    .addComponent(_mSaveAndClose)
408                    .addComponent(jButton2))
409                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
410        );
411
412        pack();
413    }// </editor-fold>//GEN-END:initComponents
414
415    private void _mSaveAndCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mSaveAndCloseActionPerformed
416        if (CommonSubs.missingFieldsErrorDialogDisplayed(this, formFieldsValid(), false)) {
417            return; // Do not allow exit or transfer of data.
418        }
419
420        _mCodeButtonHandlerData._mTUL_DispatcherInternalSensorLockToggle = CommonSubs.getNBHSensor((String) _mTUL_DispatcherInternalSensorLockToggle.getSelectedItem(), false);
421        _mCodeButtonHandlerData._mTUL_DispatcherInternalSensorUnlockedIndicator = CommonSubs.getNBHSensor((String) _mTUL_DispatcherInternalSensorUnlockedIndicator.getSelectedItem(), false);
422
423        // External turnout
424        NBHTurnout newTurnout = CommonSubs.getNBHTurnout(_mCurrentExternalTurnout, _mTUL_ExternalTurnoutFeedbackDifferent.isSelected());
425        _mCodeButtonHandlerData._mTUL_ExternalTurnout = newTurnout;
426        _mCodeButtonHandlerData._mTUL_ExternalTurnoutFeedbackDifferent = _mTUL_ExternalTurnoutFeedbackDifferent.isSelected();
427
428        // Additional turnout 1
429        newTurnout = CommonSubs.getNBHTurnout(_mCurrentAdditionalTurnout1, _mTUL_AdditionalExternalTurnout1FeedbackDifferent.isSelected());
430        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1 = newTurnout;
431        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout1FeedbackDifferent = _mTUL_AdditionalExternalTurnout1FeedbackDifferent.isSelected();
432
433        // Additional turnout 2
434        newTurnout = CommonSubs.getNBHTurnout(_mCurrentAdditionalTurnout2, _mTUL_AdditionalExternalTurnout2FeedbackDifferent.isSelected());
435        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2 = newTurnout;
436        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout2FeedbackDifferent = _mTUL_AdditionalExternalTurnout2FeedbackDifferent.isSelected();
437
438        // Additional turnout 3
439        newTurnout = CommonSubs.getNBHTurnout(_mCurrentAdditionalTurnout3, _mTUL_AdditionalExternalTurnout3FeedbackDifferent.isSelected());
440        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3 = newTurnout;
441        _mCodeButtonHandlerData._mTUL_AdditionalExternalTurnout3FeedbackDifferent = _mTUL_AdditionalExternalTurnout3FeedbackDifferent.isSelected();
442
443        // Other fields
444        _mCodeButtonHandlerData._mTUL_GUI_IconsEnabled = _mTUL_GUI_IconsEnabled.isSelected();
445        _mCodeButtonHandlerData._mTUL_NoDispatcherControlOfSwitch = _mTUL_NoDispatcherControlOfSwitch.isSelected();
446        _mCodeButtonHandlerData._mTUL_ndcos_WhenLockedSwitchStateIsClosed = _mTUL_ndcos_WhenLockedSwitchStateIsClosed.isSelected();
447        _mCodeButtonHandlerData._mTUL_LockImplementation = CodeButtonHandlerData.LOCK_IMPLEMENTATION.getLockImplementation(_mTUL_LockImplementation);
448
449        _mClosedNormally = true;
450        _mAwtWindowProperties.saveWindowState(this, FORM_PROPERTIES);
451        dispose();
452    }//GEN-LAST:event__mSaveAndCloseActionPerformed
453
454    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
455        _mAwtWindowProperties.saveWindowState(this, FORM_PROPERTIES);
456        if (CommonSubs.allowClose(this, dataChanged())) dispose();
457    }//GEN-LAST:event_formWindowClosing
458
459    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
460        CodeButtonHandlerData temp = _mCodeButtonHandlerData;
461        temp = CodeButtonHandlerDataRoutines.uECBHDWSD_TUL(_mProgramProperties, temp);
462        CommonSubs.populateJComboBoxWithBeans(_mTUL_DispatcherInternalSensorLockToggle, "Sensor", temp._mTUL_DispatcherInternalSensorLockToggle.getHandleName(), false);   // NOI18N
463        CommonSubs.populateJComboBoxWithBeans(_mTUL_DispatcherInternalSensorUnlockedIndicator, "Sensor", temp._mTUL_DispatcherInternalSensorUnlockedIndicator.getHandleName(), false);   // NOI18N
464    }//GEN-LAST:event_jButton2ActionPerformed
465
466    private void _mTUL_ExternalTurnoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mTUL_ExternalTurnoutActionPerformed
467        _mCurrentExternalTurnout = (String) _mTUL_ExternalTurnout.getSelectedItem();
468        initializeAll4LockedTurnoutJComboBoxesAndSupportingData();
469    }//GEN-LAST:event__mTUL_ExternalTurnoutActionPerformed
470
471    private void _mTUL_AdditionalExternalTurnout1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mTUL_AdditionalExternalTurnout1ActionPerformed
472        _mCurrentAdditionalTurnout1 = (String) _mTUL_AdditionalExternalTurnout1.getSelectedItem();
473        initializeAll4LockedTurnoutJComboBoxesAndSupportingData();
474    }//GEN-LAST:event__mTUL_AdditionalExternalTurnout1ActionPerformed
475
476    private void _mTUL_AdditionalExternalTurnout2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mTUL_AdditionalExternalTurnout2ActionPerformed
477        _mCurrentAdditionalTurnout2 = (String) _mTUL_AdditionalExternalTurnout2.getSelectedItem();
478        initializeAll4LockedTurnoutJComboBoxesAndSupportingData();
479    }//GEN-LAST:event__mTUL_AdditionalExternalTurnout2ActionPerformed
480
481    private void _mTUL_AdditionalExternalTurnout3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mTUL_AdditionalExternalTurnout3ActionPerformed
482        _mCurrentAdditionalTurnout3 = (String) _mTUL_AdditionalExternalTurnout3.getSelectedItem();
483        initializeAll4LockedTurnoutJComboBoxesAndSupportingData();
484    }//GEN-LAST:event__mTUL_AdditionalExternalTurnout3ActionPerformed
485
486    private void _mTUL_NoDispatcherControlOfSwitchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mTUL_NoDispatcherControlOfSwitchActionPerformed
487        // enable/disable _mTUL_ndcos_WhenLockedSwitchStateIsClosed based on NDCOS selection
488        boolean ndcpos = _mTUL_NoDispatcherControlOfSwitch.isSelected();
489        _mTUL_ndcos_WhenLockedSwitchStateIsClosed.setEnabled(ndcpos);
490        _mLabelDlgTULClosed.setEnabled(ndcpos);
491    }//GEN-LAST:event__mTUL_NoDispatcherControlOfSwitchActionPerformed
492
493    private void initializeAll4LockedTurnoutJComboBoxesAndSupportingData() {
494        if (_mIgnoreActionEvent) return;    // Process ONLY when the user selectes an item in the combo box (even if the same one), otherwise forget it.
495
496        // Turnouts used in other columns
497        HashSet<String> hashSetOfExistingLockedTurnoutsExcludingThisOne = _mCTCSerialData.getHashSetOfAllLockedTurnoutsExcludingPassedOne(_mCodeButtonHandlerData); // Once initialized, fixed!
498
499        // All turnouts minus those used in other columns
500        InstanceManager.getDefault(TurnoutManager.class).getNamedBeanSet().forEach((t) -> { _mStartingHashSetOfTurnouts.add(t.getDisplayName()); });
501        _mStartingHashSetOfTurnouts.removeAll(hashSetOfExistingLockedTurnoutsExcludingThisOne);
502
503        // Retain the selected turnout.  The list can changed based on selections and which combo box.
504        _mArrayListOfThisRecordsUsedLockedTurnouts.clear();
505        _mArrayListOfThisRecordsUsedLockedTurnouts.add(_mCurrentExternalTurnout);
506        _mArrayListOfThisRecordsUsedLockedTurnouts.add(_mCurrentAdditionalTurnout1);
507        _mArrayListOfThisRecordsUsedLockedTurnouts.add(_mCurrentAdditionalTurnout2);
508        _mArrayListOfThisRecordsUsedLockedTurnouts.add(_mCurrentAdditionalTurnout3);
509
510        // Update the combo boxes
511        update1LockedTurnoutJComboBox(_mTUL_ExternalTurnout, 0, _mCurrentExternalTurnout);
512        update1LockedTurnoutJComboBox(_mTUL_AdditionalExternalTurnout1, 1, _mCurrentAdditionalTurnout1);
513        update1LockedTurnoutJComboBox(_mTUL_AdditionalExternalTurnout2, 2, _mCurrentAdditionalTurnout2);
514        update1LockedTurnoutJComboBox(_mTUL_AdditionalExternalTurnout3, 3, _mCurrentAdditionalTurnout3);
515    }
516
517    private void update1LockedTurnoutJComboBox(JComboBox<String> jComboBox, int index, String currentSelection) {
518        HashSet<String> ultimateHashSet = new HashSet<>(_mStartingHashSetOfTurnouts);   // Make a deep copy.
519        ultimateHashSet.removeAll(returnHashSetSubset(index));
520        populateJComboBox(jComboBox, ultimateHashSet, currentSelection);
521    }
522
523    /**
524     * Just returns a sub-set of _mArrayListOfThisRecordsUsedLockedTurnouts excluding
525     * any blank entries, and the one index passed.
526     *
527     * @param indexToLeaveOff The JComboBox "field" we will be editing: 0 = _mTUL_ExternalTurnout, 1 = _mTUL_AdditionalExternalTurnout1, 2 = _mTUL_AdditionalExternalTurnout2, 3 = _mTUL_AdditionalExternalTurnout3
528     * @return The requested subset of _mArrayListOfThisRecordsUsedLockedTurnouts
529     */
530    private HashSet<String> returnHashSetSubset(int indexToLeaveOff) {
531        HashSet<String> returnValue = new HashSet<>();
532        for (int index = 0; index < _mArrayListOfThisRecordsUsedLockedTurnouts.size(); index++) {
533
534            String recordUsed = _mArrayListOfThisRecordsUsedLockedTurnouts.get(index);
535            boolean recordValid = (recordUsed == null || recordUsed.isEmpty()) ? false : true;
536            if (index != indexToLeaveOff && recordValid) {
537                returnValue.add(recordUsed);
538            }
539        }
540        return returnValue;
541    }
542
543    /**
544     *
545     * This is a DIRECT plagiarization of Dave Sands CommonSubs.populateJComboBoxWithBeans, repurposed to support
546     * what is needed specifically by Turnout Locking.
547     * It does not have the flexibility of the original routine, since thats not needed.
548     * (see "_mIgnoreActionEvent", since I don't know of another way to do it).
549     *
550     * Populate a combo box with bean names using getDisplayName().
551     * <p>
552     * If a panel xml file has not been loaded, the combo box will behave as a
553     * text field (editable), otherwise it will behave as standard combo box (not editable).
554     * @param jComboBox The string based combo box to be populated.
555     * @param populateWith A hash set that needs to be sorted first, to populate the drop down list with.
556     * @param currentSelection The current item to be selected, none if null.
557     */
558    public void populateJComboBox(JComboBox<String> jComboBox, HashSet<String> populateWith, String currentSelection) {
559        _mIgnoreActionEvent = true;
560        jComboBox.removeAllItems();
561        jComboBox.setEditable(false);
562        ArrayList<String> list = new ArrayList<>(populateWith);
563        list.sort(new jmri.util.AlphanumComparator());
564        list.forEach((item) -> {
565            jComboBox.addItem(item);
566        });
567        jmri.util.swing.JComboBoxUtil.setupComboBoxMaxRows(jComboBox);
568        jComboBox.setSelectedItem(currentSelection);
569        jComboBox.insertItemAt("", 0);
570        if (currentSelection == null || currentSelection.isEmpty()) {
571            jComboBox.setSelectedIndex(0);
572        }
573        _mIgnoreActionEvent = false;
574    }
575
576    // Variables declaration - do not modify//GEN-BEGIN:variables
577    private javax.swing.JLabel _mLabelDlgTULClosed;
578    private javax.swing.JLabel _mLabelDlgTULGUIEnable;
579    private javax.swing.JButton _mSaveAndClose;
580    private javax.swing.JLabel _mTUL_ActualTurnoutPrompt;
581    private javax.swing.JComboBox<String> _mTUL_AdditionalExternalTurnout1;
582    private javax.swing.JCheckBox _mTUL_AdditionalExternalTurnout1FeedbackDifferent;
583    private javax.swing.JComboBox<String> _mTUL_AdditionalExternalTurnout2;
584    private javax.swing.JCheckBox _mTUL_AdditionalExternalTurnout2FeedbackDifferent;
585    private javax.swing.JComboBox<String> _mTUL_AdditionalExternalTurnout3;
586    private javax.swing.JCheckBox _mTUL_AdditionalExternalTurnout3FeedbackDifferent;
587    private javax.swing.JComboBox<String> _mTUL_DispatcherInternalSensorLockToggle;
588    private javax.swing.JComboBox<String> _mTUL_DispatcherInternalSensorUnlockedIndicator;
589    private javax.swing.JComboBox<String> _mTUL_ExternalTurnout;
590    private javax.swing.JCheckBox _mTUL_ExternalTurnoutFeedbackDifferent;
591    private javax.swing.JCheckBox _mTUL_GUI_IconsEnabled;
592    private javax.swing.ButtonGroup _mTUL_LockImplementation;
593    private javax.swing.JCheckBox _mTUL_NoDispatcherControlOfSwitch;
594    private javax.swing.JCheckBox _mTUL_ndcos_WhenLockedSwitchStateIsClosed;
595    private javax.swing.JButton jButton2;
596    private javax.swing.JLabel jLabel1;
597    private javax.swing.JLabel jLabel11;
598    private javax.swing.JLabel jLabel2;
599    private javax.swing.JLabel jLabel4;
600    private javax.swing.JLabel jLabel6;
601    private javax.swing.JLabel jLabel7;
602    private javax.swing.JRadioButton jRadioButton1;
603    private javax.swing.JRadioButton jRadioButton2;
604    // End of variables declaration//GEN-END:variables
605}