001package jmri.jmrit.ctc.editor.gui;
002
003import java.awt.Color;
004import java.awt.event.WindowAdapter;
005import java.awt.event.WindowEvent;
006import java.util.ArrayList;
007
008import jmri.jmrit.ctc.ctcserialdata.CTCSerialData;
009import jmri.jmrit.ctc.ctcserialdata.CodeButtonHandlerData;
010import jmri.jmrit.ctc.ctcserialdata.OtherData;
011import jmri.jmrit.ctc.ctcserialdata.TrafficLockingData;
012import jmri.jmrit.ctc.editor.code.AwtWindowProperties;
013import jmri.jmrit.ctc.editor.code.CheckJMRIObject;
014import jmri.jmrit.ctc.editor.code.CommonSubs;
015import jmri.jmrit.ctc.topology.Topology;
016import jmri.jmrit.ctc.topology.TopologyInfo;
017
018/**
019 *
020 * @author Gregory J. Bedlek Copyright (C) 2018, 2019
021 */
022public class FrmTRL extends javax.swing.JFrame {
023
024    /**
025     * Creates new form DlgTRL
026     */
027    private static final String FORM_PROPERTIES = "DlgTRL";     // NOI18N
028    private final AwtWindowProperties _mAwtWindowProperties;
029    private boolean _mClosedNormally = false;
030    public boolean closedNormally() { return _mClosedNormally; }
031    private final CodeButtonHandlerData _mCodeButtonHandlerData;
032    private final CTCSerialData _mCTCSerialData;
033    private final CheckJMRIObject _mCheckJMRIObject;
034    private final FrmMainForm _mMainForm;
035    private Topology _mTopology;
036
037    private void initOrig() {
038    }
039    private boolean dataChanged() {
040        return false;
041    }
042
043    public FrmTRL(  AwtWindowProperties awtWindowProperties, CodeButtonHandlerData codeButtonHandlerData,
044                    CTCSerialData ctcSerialData, CheckJMRIObject checkJMRIObject) {
045        super();
046        initComponents();
047        CommonSubs.addHelpMenu(this, "package.jmri.jmrit.ctc.CTC_frmTRL", true);  // NOI18N
048        _mMainForm = jmri.InstanceManager.getDefault(FrmMainForm.class);
049        _mAwtWindowProperties = awtWindowProperties;
050        _mCodeButtonHandlerData = codeButtonHandlerData;
051        _mCTCSerialData = ctcSerialData;
052        _mCheckJMRIObject = checkJMRIObject;
053        initOrig();
054        _mAwtWindowProperties.setWindowState(this, FORM_PROPERTIES);
055        this.getRootPane().setDefaultButton(_mOK);
056        updateRuleCounts();
057        this.setTitle(Bundle.getMessage("TitleDlgTRL") + " " + codeButtonHandlerData.myShortStringNoComma());   // NOI18N
058        ArrayList<String> listOfOSSectionOccupiedExternalSensors = getListOfExternalSensorsSlaved(codeButtonHandlerData, _mCTCSerialData.getCodeButtonHandlerDataArrayList());
059        _mTopology = new Topology(_mCTCSerialData, listOfOSSectionOccupiedExternalSensors, Bundle.getMessage("TLE_Normal"), Bundle.getMessage("TLE_Reverse"));  // NOI18N
060        boolean isMastSignalType = _mCTCSerialData.getOtherData()._mSignalSystemType == OtherData.SIGNAL_SYSTEM_TYPE.SIGNALMAST;
061        boolean topologyAvailable = _mTopology.isTopologyAvailable() && isMastSignalType;
062        _mAutoGenerate.setVisible(topologyAvailable);
063        _mReverseLeftRight.setVisible(topologyAvailable);
064        _mAutoGenerateWarning.setVisible(topologyAvailable);
065    }
066
067    private ArrayList<String> getListOfExternalSensorsSlaved(   CodeButtonHandlerData currentCodeButtonHandlerData,
068                                                                ArrayList <CodeButtonHandlerData> codeButtonHandlerDataArrayList) {
069        ArrayList<String> returnValue = new ArrayList<>();
070        returnValue.add(currentCodeButtonHandlerData._mOSSectionOccupiedExternalSensor.getHandleName());    // Put ours in there at least.
071        int currentUniqueID = currentCodeButtonHandlerData._mUniqueID;
072        for (CodeButtonHandlerData codeButtonHandlerData : codeButtonHandlerDataArrayList) {
073            if (currentCodeButtonHandlerData != codeButtonHandlerData    // Don't check ourselves, we've already put us in the list.
074            && codeButtonHandlerData._mOSSectionSwitchSlavedToUniqueID != CodeButtonHandlerData.SWITCH_NOT_SLAVED   // It's referencing someone else:
075            && currentUniqueID == codeButtonHandlerData._mOSSectionSwitchSlavedToUniqueID) {  // And it's referening "us"/
076                returnValue.add(codeButtonHandlerData._mOSSectionOccupiedExternalSensor.getHandleName());
077            }
078        }
079        return returnValue;
080    }
081
082    public static boolean dialogCodeButtonHandlerDataValid(CheckJMRIObject checkJMRIObject, CodeButtonHandlerData codeButtonHandlerData) {
083        if (!valid(checkJMRIObject, codeButtonHandlerData._mTRL_LeftTrafficLockingRules)) return false;
084        if (!valid(checkJMRIObject, codeButtonHandlerData._mTRL_RightTrafficLockingRules)) return false;
085        return true;
086    }
087
088    private void updateRuleCounts() {
089        _mLeftNumberOfRules.setText(Bundle.getMessage("InfoDlgTRLRules") + " " + Integer.toString(_mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules.size()));   // NOI18N
090        _mRightNumberOfRules.setText(Bundle.getMessage("InfoDlgTRLRules") + " " + Integer.toString(_mCodeButtonHandlerData._mTRL_RightTrafficLockingRules.size()));      // NOI18N
091        _mLeftNumberOfRulesPrompt.setForeground(valid(_mCheckJMRIObject, _mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules) ? Color.black : Color.red);
092        _mRightNumberOfRulesPrompt.setForeground(valid(_mCheckJMRIObject, _mCodeButtonHandlerData._mTRL_RightTrafficLockingRules) ? Color.black : Color.red);
093    }
094
095    private static boolean valid(CheckJMRIObject checkJMRIObject, ArrayList<TrafficLockingData> trafficLockingRules) {
096        for (TrafficLockingData trafficLockingRule : trafficLockingRules) {
097            if (!checkJMRIObject.validClass(trafficLockingRule)) return false; // Error
098        }
099        return true;    // All valid
100    }
101
102    /**
103     * This method is called from within the constructor to initialize the form.
104     * WARNING: Do NOT modify this code. The content of this method is always
105     * regenerated by the Form Editor.
106     */
107    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
108    private void initComponents() {
109
110        _mEditLeftTrafficLockingRules = new javax.swing.JButton();
111        _mEditRightTrafficLockingRules = new javax.swing.JButton();
112        _mLeftNumberOfRulesPrompt = new javax.swing.JLabel();
113        _mRightNumberOfRulesPrompt = new javax.swing.JLabel();
114        _mOK = new javax.swing.JButton();
115        _mLeftNumberOfRules = new javax.swing.JLabel();
116        _mRightNumberOfRules = new javax.swing.JLabel();
117        jLabel10 = new javax.swing.JLabel();
118        jLabel4 = new javax.swing.JLabel();
119        jLabel11 = new javax.swing.JLabel();
120        _mAutoGenerate = new javax.swing.JButton();
121        _mReverseLeftRight = new javax.swing.JButton();
122        _mAutoGenerateWarning = new javax.swing.JLabel();
123
124        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
125        setTitle(Bundle.getMessage("TitleDlgTRL"));
126        addWindowListener(new java.awt.event.WindowAdapter() {
127            @Override
128            public void windowClosing(java.awt.event.WindowEvent evt) {
129                formWindowClosing(evt);
130            }
131        });
132
133        _mEditLeftTrafficLockingRules.setText(Bundle.getMessage("LabelDlgTRLEdit"));
134        _mEditLeftTrafficLockingRules.addActionListener(new java.awt.event.ActionListener() {
135            @Override
136            public void actionPerformed(java.awt.event.ActionEvent evt) {
137                _mEditLeftTrafficLockingRulesActionPerformed(evt);
138            }
139        });
140
141        _mEditRightTrafficLockingRules.setText(Bundle.getMessage("LabelDlgTRLEdit"));
142        _mEditRightTrafficLockingRules.addActionListener(new java.awt.event.ActionListener() {
143            @Override
144            public void actionPerformed(java.awt.event.ActionEvent evt) {
145                _mEditRightTrafficLockingRulesActionPerformed(evt);
146            }
147        });
148
149        _mLeftNumberOfRulesPrompt.setText(Bundle.getMessage("LabelDlgTRLLeft"));
150
151        _mRightNumberOfRulesPrompt.setText(Bundle.getMessage("LabelDlgTRLRight"));
152
153        _mOK.setText(Bundle.getMessage("ButtonOK"));
154        _mOK.addActionListener(new java.awt.event.ActionListener() {
155            @Override
156            public void actionPerformed(java.awt.event.ActionEvent evt) {
157                _mOKActionPerformed(evt);
158            }
159        });
160
161        _mLeftNumberOfRules.setText(Bundle.getMessage("InfoDlgTRLRulesQuestion"));
162
163        _mRightNumberOfRules.setText(Bundle.getMessage("InfoDlgTRLRulesQuestion"));
164
165        jLabel10.setText(Bundle.getMessage("InfoDlgTRLNote2"));
166
167        jLabel4.setText(Bundle.getMessage("InfoDlgTRLNote1"));
168
169        jLabel11.setText(Bundle.getMessage("InfoDlgTRLNote3"));
170
171        _mAutoGenerate.setText(Bundle.getMessage("LabelDlgTRLAutoGenerate"));
172        _mAutoGenerate.addActionListener(new java.awt.event.ActionListener() {
173            @Override
174            public void actionPerformed(java.awt.event.ActionEvent evt) {
175                _mAutoGenerateActionPerformed(evt);
176            }
177        });
178
179        _mReverseLeftRight.setText(Bundle.getMessage("LabelDlgTRLReverseLeftRight"));
180        _mReverseLeftRight.addActionListener(new java.awt.event.ActionListener() {
181            @Override
182            public void actionPerformed(java.awt.event.ActionEvent evt) {
183                _mReverseLeftRightActionPerformed(evt);
184            }
185        });
186
187        _mAutoGenerateWarning.setText(Bundle.getMessage("LabelDlgTRLAutoGenerateWarning"));
188
189        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
190        getContentPane().setLayout(layout);
191        layout.setHorizontalGroup(
192            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193            .addGroup(layout.createSequentialGroup()
194                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
195                    .addGroup(layout.createSequentialGroup()
196                        .addGap(49, 49, 49)
197                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
198                            .addComponent(_mLeftNumberOfRulesPrompt)
199                            .addComponent(_mRightNumberOfRulesPrompt))
200                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
201                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
202                            .addGroup(layout.createSequentialGroup()
203                                .addComponent(_mEditRightTrafficLockingRules)
204                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
205                                .addComponent(_mRightNumberOfRules, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
206                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
207                                .addComponent(_mReverseLeftRight))
208                            .addGroup(layout.createSequentialGroup()
209                                .addComponent(_mEditLeftTrafficLockingRules)
210                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
211                                .addComponent(_mLeftNumberOfRules, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
212                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
213                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
214                                    .addComponent(_mAutoGenerateWarning)
215                                    .addComponent(_mAutoGenerate, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE)))))
216                    .addGroup(layout.createSequentialGroup()
217                        .addContainerGap()
218                        .addComponent(jLabel4))
219                    .addGroup(layout.createSequentialGroup()
220                        .addContainerGap()
221                        .addComponent(jLabel10))
222                    .addGroup(layout.createSequentialGroup()
223                        .addContainerGap()
224                        .addComponent(jLabel11))
225                    .addGroup(layout.createSequentialGroup()
226                        .addGap(164, 164, 164)
227                        .addComponent(_mOK)))
228                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
229        );
230        layout.setVerticalGroup(
231            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
232            .addGroup(layout.createSequentialGroup()
233                .addContainerGap()
234                .addComponent(_mAutoGenerateWarning)
235                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
236                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
237                    .addComponent(_mLeftNumberOfRulesPrompt)
238                    .addComponent(_mEditLeftTrafficLockingRules)
239                    .addComponent(_mLeftNumberOfRules)
240                    .addComponent(_mAutoGenerate))
241                .addGap(18, 18, 18)
242                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
243                    .addComponent(_mEditRightTrafficLockingRules)
244                    .addComponent(_mRightNumberOfRulesPrompt)
245                    .addComponent(_mRightNumberOfRules)
246                    .addComponent(_mReverseLeftRight))
247                .addGap(13, 13, 13)
248                .addComponent(jLabel4)
249                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
250                .addComponent(jLabel10)
251                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
252                .addComponent(jLabel11)
253                .addGap(18, 18, 18)
254                .addComponent(_mOK)
255                .addContainerGap(31, Short.MAX_VALUE))
256        );
257
258        pack();
259    }// </editor-fold>//GEN-END:initComponents
260
261    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
262        _mAwtWindowProperties.saveWindowState(this, FORM_PROPERTIES);
263        if (CommonSubs.allowClose(this, dataChanged())) dispose();
264    }//GEN-LAST:event_formWindowClosing
265
266    private void _mEditLeftTrafficLockingRulesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mEditLeftTrafficLockingRulesActionPerformed
267        if (_mMainForm._mTRL_RulesFormOpen) return;
268        _mMainForm._mTRL_RulesFormOpen = true;
269        FrmTRL_Rules dialog = new FrmTRL_Rules( _mAwtWindowProperties, _mCodeButtonHandlerData,
270                                                true, _mCTCSerialData, _mCheckJMRIObject);
271        dialog.addWindowListener(new WindowAdapter() {
272            @Override
273            public void windowClosed(WindowEvent e) {
274                if (dialog.closedNormally()) {
275                    _mClosedNormally = true;
276                    updateRuleCounts();
277                }
278                _mMainForm._mTRL_RulesFormOpen = false;
279            }
280        });
281        dialog.setVisible(true);  // MUST BE AFTER "addWindowListener"!  BUG IN AWT/SWING!
282    }//GEN-LAST:event__mEditLeftTrafficLockingRulesActionPerformed
283
284    private void _mEditRightTrafficLockingRulesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mEditRightTrafficLockingRulesActionPerformed
285        if (_mMainForm._mTRL_RulesFormOpen) return;
286        _mMainForm._mTRL_RulesFormOpen = true;
287        FrmTRL_Rules dialog = new FrmTRL_Rules( _mAwtWindowProperties, _mCodeButtonHandlerData,
288                                                false, _mCTCSerialData, _mCheckJMRIObject);
289        dialog.addWindowListener(new WindowAdapter() {
290            @Override
291            public void windowClosed(WindowEvent e) {
292                if (dialog.closedNormally()) {
293                    _mClosedNormally = true;
294                    updateRuleCounts();
295                }
296                _mMainForm._mTRL_RulesFormOpen = false;
297            }
298        });
299        dialog.setVisible(true);  // MUST BE AFTER "addWindowListener"!  BUG IN AWT/SWING!
300    }//GEN-LAST:event__mEditRightTrafficLockingRulesActionPerformed
301
302    private void _mOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mOKActionPerformed
303        dispose();
304    }//GEN-LAST:event__mOKActionPerformed
305
306    private void _mReverseLeftRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mReverseLeftRightActionPerformed
307        ArrayList<TrafficLockingData> blah = _mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules;
308        _mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules = _mCodeButtonHandlerData._mTRL_RightTrafficLockingRules;
309        _mCodeButtonHandlerData._mTRL_RightTrafficLockingRules = blah;
310        updateRuleCounts();
311    }//GEN-LAST:event__mReverseLeftRightActionPerformed
312
313    private void _mAutoGenerateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mAutoGenerateActionPerformed
314
315        ArrayList<TopologyInfo> topologyInfosArrayList = _mTopology.getTrafficLockingRules(true);        // Left traffic.
316        _mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules.clear();
317        for (int index = 0; index < topologyInfosArrayList.size(); index++) {
318            TopologyInfo topologyInfo = topologyInfosArrayList.get(index);
319            TrafficLockingData trafficLockingData = new TrafficLockingData(index + 1, topologyInfo.getDestinationSignalMast(), topologyInfo);
320            _mCodeButtonHandlerData._mTRL_LeftTrafficLockingRules.add(trafficLockingData);
321        }
322
323        topologyInfosArrayList = _mTopology.getTrafficLockingRules(false);        // Right traffic.
324        _mCodeButtonHandlerData._mTRL_RightTrafficLockingRules.clear();
325        for (int index = 0; index < topologyInfosArrayList.size(); index++) {
326            TopologyInfo topologyInfo = topologyInfosArrayList.get(index);
327            TrafficLockingData trafficLockingData = new TrafficLockingData(index + 1, topologyInfo.getDestinationSignalMast(), topologyInfo);
328            _mCodeButtonHandlerData._mTRL_RightTrafficLockingRules.add(trafficLockingData);
329        }
330
331        updateRuleCounts();
332    }//GEN-LAST:event__mAutoGenerateActionPerformed
333
334    // Variables declaration - do not modify//GEN-BEGIN:variables
335    private javax.swing.JButton _mAutoGenerate;
336    private javax.swing.JLabel _mAutoGenerateWarning;
337    private javax.swing.JButton _mEditLeftTrafficLockingRules;
338    private javax.swing.JButton _mEditRightTrafficLockingRules;
339    private javax.swing.JLabel _mLeftNumberOfRules;
340    private javax.swing.JLabel _mLeftNumberOfRulesPrompt;
341    private javax.swing.JButton _mOK;
342    private javax.swing.JButton _mReverseLeftRight;
343    private javax.swing.JLabel _mRightNumberOfRules;
344    private javax.swing.JLabel _mRightNumberOfRulesPrompt;
345    private javax.swing.JLabel jLabel10;
346    private javax.swing.JLabel jLabel11;
347    private javax.swing.JLabel jLabel4;
348    // End of variables declaration//GEN-END:variables
349}