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.CommonSubs;
006import java.util.ArrayList;
007import javax.swing.JComboBox;
008import javax.swing.JTable;
009import javax.swing.table.DefaultTableModel;
010import jmri.jmrit.ctc.ctcserialdata.CTCSerialData;
011import jmri.jmrit.ctc.ctcserialdata.CodeButtonHandlerData;
012import jmri.jmrit.ctc.ctcserialdata.ProjectsCommonSubs;
013
014/**
015 * @author Gregory J. Bedlek Copyright (C) 2018, 2019
016 */
017public class FrmIL extends javax.swing.JFrame {
018
019    /**
020     * Creates new form DlgIL
021     */
022    private static final String FORM_PROPERTIES = "DlgIL";  // NOI18N
023    private static final String PREFIX = "_mIL_";           // NOI18N
024    private final AwtWindowProperties _mAwtWindowProperties;
025    private boolean _mClosedNormally = false;
026    public boolean closedNormally() { return _mClosedNormally; }
027    private final CodeButtonHandlerData _mCodeButtonHandlerData;
028    private final CheckJMRIObject _mCheckJMRIObject;
029    private final boolean _mSignalHeadSelected;
030    private final CTCSerialData _mCTCSerialData;
031    private final ArrayList<Integer> _mUniqueIDS = new ArrayList<>();
032
033    private ArrayList<String> _mSignalsArrayListOrig;
034    private void initOrig(ArrayList<String> signalsArrayList) {
035        _mSignalsArrayListOrig = new ArrayList<>();
036        for (int index = 0; index < signalsArrayList.size(); index++) {
037            _mSignalsArrayListOrig.add(signalsArrayList.get(index));
038        }
039    }
040    private boolean dataChanged() {
041        int tableLength = CommonSubs.compactDefaultTableModel(_mIL_TableOfExternalSignalNamesDefaultTableModel);
042        if (tableLength != _mSignalsArrayListOrig.size()) return true;
043        for (int index = 0; index < tableLength; index++) {
044            if (!_mSignalsArrayListOrig.get(index).equals(_mIL_TableOfExternalSignalNamesDefaultTableModel.getValueAt(index, 0))) return true;
045        }
046        return false;
047    }
048
049    private final DefaultTableModel _mIL_TableOfExternalSignalNamesDefaultTableModel;
050
051    public FrmIL(   AwtWindowProperties awtWindowProperties,
052                    CodeButtonHandlerData codeButtonHandlerData,
053                    CheckJMRIObject checkJMRIObject,
054                    boolean signalHeadSelected,
055                    CTCSerialData ctcSerialData) {
056        super();
057        initComponents();
058        CommonSubs.addHelpMenu(this, "package.jmri.jmrit.ctc.CTC_frmIL", true);  // NOI18N
059        _mAwtWindowProperties = awtWindowProperties;
060        _mCodeButtonHandlerData = codeButtonHandlerData;
061        _mCheckJMRIObject = checkJMRIObject;
062        _mSignalHeadSelected = signalHeadSelected;
063        _mCTCSerialData = ctcSerialData;
064        _mIL_TableOfExternalSignalNamesDefaultTableModel = (DefaultTableModel)_mIL_TableOfExternalSignalNames.getModel();
065        ArrayList<String> signalsArrayList = ProjectsCommonSubs.getArrayListOfSignalNames(_mCodeButtonHandlerData._mIL_Signals);
066        loadUpSignalTable(signalsArrayList);
067        initOrig(signalsArrayList);
068
069        _mAwtWindowProperties.setWindowState(this, FORM_PROPERTIES);
070        this.getRootPane().setDefaultButton(_mSaveAndClose);
071
072        enableSignalListComboBox(_mIL_TableOfExternalSignalNames);
073        boolean anyAvailable = CommonSubs.populateJComboBoxWithColumnDescriptionsExceptOurs(_mOS_NumberEntry, _mCTCSerialData, _mCodeButtonHandlerData._mUniqueID, _mUniqueIDS);
074        BT_Replace.setEnabled(anyAvailable);
075    }
076
077    public static boolean dialogCodeButtonHandlerDataValid(CheckJMRIObject checkJMRIObject, CodeButtonHandlerData codeButtonHandlerData) {
078        if (!codeButtonHandlerData._mIL_Enabled) return true; // Not enabled, can be no error!
079//  Checks:
080        if (codeButtonHandlerData._mIL_Signals.isEmpty()) return false;
081        for (String signalName : ProjectsCommonSubs.getArrayListOfSignalNames(codeButtonHandlerData._mIL_Signals)) {
082            if (checkJMRIObject.checkSignal(signalName) == false) return false;
083        }
084        return checkJMRIObject.validClassWithPrefix(PREFIX, codeButtonHandlerData);
085    }
086
087//  Validate all internal fields as much as possible:
088    private ArrayList<String> formFieldsValid() {
089        ArrayList<String> errors = new ArrayList<>();
090//  Checks:
091        if (CommonSubs.getCSVStringFromDefaultTableModel(_mIL_TableOfExternalSignalNamesDefaultTableModel).isEmpty()) {
092            errors.add(Bundle.getMessage("InfoDlgILNoEntriesIn") + " \"" + _mTableOfSignalNamesPrompt.getText() + "\"");    // NOI18N
093        }
094        _mCheckJMRIObject.analyzeForm(PREFIX, this, errors);
095        return errors;
096    }
097
098    /**
099     * Add a signal head/mast combo box as the default cell editor.
100     * @param table The signal table to be modified.
101     */
102    public void enableSignalListComboBox(JTable table) {
103        // Create the signals combo box
104        JComboBox<String> comboBox = new JComboBox<>();
105        // Since IL does not have a signal type field, use the SIDI signal type
106        if (_mSignalHeadSelected) {
107            CommonSubs.populateJComboBoxWithBeans(comboBox, "SignalHead", null, true);
108        } else {
109            CommonSubs.populateJComboBoxWithBeans(comboBox, "SignalMast", null, true);
110        }
111
112        // Update the signal list cell editor
113        table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
114        table.getColumnModel().getColumn(0).setCellEditor(new javax.swing.DefaultCellEditor(comboBox));
115    }
116
117    private void loadUpSignalTable(ArrayList<String> signalsArrayList) {
118        int signalsArrayLength = signalsArrayList.size();
119        if (signalsArrayLength > _mIL_TableOfExternalSignalNames.getRowCount()) { // Has more than default (100 as of this writing) rows:
120            _mIL_TableOfExternalSignalNamesDefaultTableModel.setRowCount(signalsArrayLength);
121        }
122        for (int index = 0; index < signalsArrayLength; index++) {
123            _mIL_TableOfExternalSignalNamesDefaultTableModel.setValueAt(signalsArrayList.get(index), index, 0);
124        }
125    }
126
127    /**
128     * This method is called from within the constructor to initialize the form.
129     * WARNING: Do NOT modify this code. The content of this method is always
130     * regenerated by the Form Editor.
131     */
132    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
133    private void initComponents() {
134
135        _mSaveAndClose = new javax.swing.JButton();
136        jScrollPane1 = new javax.swing.JScrollPane();
137        _mIL_TableOfExternalSignalNames = new javax.swing.JTable();
138        jButton1 = new javax.swing.JButton();
139        jLabel4 = new javax.swing.JLabel();
140        jLabel1 = new javax.swing.JLabel();
141        jLabel5 = new javax.swing.JLabel();
142        jLabel6 = new javax.swing.JLabel();
143        _mTableOfSignalNamesPrompt = new javax.swing.JLabel();
144        jLabel2 = new javax.swing.JLabel();
145        _mOS_NumberEntry = new javax.swing.JComboBox<>();
146        BT_Replace = new javax.swing.JButton();
147
148        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
149        setTitle(Bundle.getMessage("TitleDlgIL"));
150        addWindowListener(new java.awt.event.WindowAdapter() {
151            @Override
152            public void windowClosing(java.awt.event.WindowEvent evt) {
153                formWindowClosing(evt);
154            }
155        });
156
157        _mSaveAndClose.setText(Bundle.getMessage("ButtonSaveClose"));
158        _mSaveAndClose.addActionListener(new java.awt.event.ActionListener() {
159            @Override
160            public void actionPerformed(java.awt.event.ActionEvent evt) {
161                _mSaveAndCloseActionPerformed(evt);
162            }
163        });
164
165        _mIL_TableOfExternalSignalNames.setModel(new javax.swing.table.DefaultTableModel(
166            new Object [][] {
167                {null},
168                {null},
169                {null},
170                {null},
171                {null},
172                {null},
173                {null},
174                {null},
175                {null},
176                {null},
177                {null},
178                {null},
179                {null},
180                {null},
181                {null},
182                {null},
183                {null},
184                {null},
185                {null},
186                {null},
187                {null},
188                {null},
189                {null},
190                {null},
191                {null},
192                {null},
193                {null},
194                {null},
195                {null},
196                {null},
197                {null},
198                {null},
199                {null},
200                {null},
201                {null},
202                {null},
203                {null},
204                {null},
205                {null},
206                {null},
207                {null},
208                {null},
209                {null},
210                {null},
211                {null},
212                {null},
213                {null},
214                {null},
215                {null},
216                {null},
217                {null},
218                {null},
219                {null},
220                {null},
221                {null},
222                {null},
223                {null},
224                {null},
225                {null},
226                {null},
227                {null},
228                {null},
229                {null},
230                {null},
231                {null},
232                {null},
233                {null},
234                {null},
235                {null},
236                {null},
237                {null},
238                {null},
239                {null},
240                {null},
241                {null},
242                {null},
243                {null},
244                {null},
245                {null},
246                {null},
247                {null},
248                {null},
249                {null},
250                {null},
251                {null},
252                {null},
253                {null},
254                {null},
255                {null},
256                {null},
257                {null},
258                {null},
259                {null},
260                {null},
261                {null},
262                {null},
263                {null},
264                {null},
265                {null},
266                {null}
267            },
268            new String [] {
269                ""
270            }
271        ) {
272            Class<?>[] types = new Class<?> [] {
273                java.lang.String.class
274            };
275
276            @Override
277            public Class<?> getColumnClass(int columnIndex) {
278                return types [columnIndex];
279            }
280        });
281        _mIL_TableOfExternalSignalNames.setRowHeight(18);
282        jScrollPane1.setViewportView(_mIL_TableOfExternalSignalNames);
283
284        jButton1.setText(Bundle.getMessage("ButtonDlgILCompact"));
285        jButton1.addActionListener(new java.awt.event.ActionListener() {
286            @Override
287            public void actionPerformed(java.awt.event.ActionEvent evt) {
288                jButton1ActionPerformed(evt);
289            }
290        });
291
292        jLabel4.setText(Bundle.getMessage("InfoDlgILRemove"));
293
294        jLabel1.setText(Bundle.getMessage("InfoDlgILNonRed"));
295
296        jLabel5.setText(Bundle.getMessage("InfoDlgILLocked"));
297
298        jLabel6.setText(Bundle.getMessage("InfoDlgILAutomatic"));
299
300        _mTableOfSignalNamesPrompt.setText(Bundle.getMessage("LabelDlgILNames"));
301
302        jLabel2.setText(Bundle.getMessage("LabelDlgILReplaceSet"));
303
304        BT_Replace.setText(Bundle.getMessage("ButtonDlgILReplace"));
305        BT_Replace.addActionListener(new java.awt.event.ActionListener() {
306            @Override
307            public void actionPerformed(java.awt.event.ActionEvent evt) {
308                BT_ReplaceActionPerformed(evt);
309            }
310        });
311
312        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
313        getContentPane().setLayout(layout);
314        layout.setHorizontalGroup(
315            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
316            .addGroup(layout.createSequentialGroup()
317                .addContainerGap()
318                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
319                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
320                    .addComponent(_mTableOfSignalNamesPrompt))
321                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
322                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
323                    .addComponent(jLabel1)
324                    .addComponent(jLabel5)
325                    .addComponent(jButton1)
326                    .addComponent(jLabel4)
327                    .addGroup(layout.createSequentialGroup()
328                        .addComponent(_mSaveAndClose)
329                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
330                        .addComponent(jLabel6))
331                    .addComponent(jLabel2)
332                    .addGroup(layout.createSequentialGroup()
333                        .addComponent(_mOS_NumberEntry, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
334                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
335                        .addComponent(BT_Replace)))
336                .addGap(123, 123, 123))
337        );
338        layout.setVerticalGroup(
339            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
340            .addGroup(layout.createSequentialGroup()
341                .addContainerGap()
342                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
343                    .addComponent(jLabel1)
344                    .addComponent(_mTableOfSignalNamesPrompt, javax.swing.GroupLayout.Alignment.TRAILING))
345                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
346                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
347                    .addGroup(layout.createSequentialGroup()
348                        .addComponent(jLabel5)
349                        .addGap(47, 47, 47)
350                        .addComponent(jLabel4)
351                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
352                        .addComponent(jButton1)
353                        .addGap(18, 18, 18)
354                        .addComponent(jLabel2)
355                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
356                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
357                            .addComponent(_mOS_NumberEntry, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
358                            .addComponent(BT_Replace))
359                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 155, Short.MAX_VALUE)
360                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
361                            .addComponent(_mSaveAndClose)
362                            .addComponent(jLabel6)))
363                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
364                .addContainerGap())
365        );
366
367        pack();
368    }// </editor-fold>//GEN-END:initComponents
369
370    private void _mSaveAndCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__mSaveAndCloseActionPerformed
371        if (CommonSubs.missingFieldsErrorDialogDisplayed(this, formFieldsValid(), false)) {
372            return; // Do not allow exit or transfer of data.
373        }
374        _mCodeButtonHandlerData._mIL_Signals = ProjectsCommonSubs.getArrayListOfSignals(
375                CommonSubs.getStringArrayFromDefaultTableModel(
376                _mIL_TableOfExternalSignalNamesDefaultTableModel));
377        _mClosedNormally = true;
378        _mAwtWindowProperties.saveWindowState(this, FORM_PROPERTIES);
379        dispose();
380    }//GEN-LAST:event__mSaveAndCloseActionPerformed
381
382    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
383        _mAwtWindowProperties.saveWindowState(this, FORM_PROPERTIES);
384        if (CommonSubs.allowClose(this, dataChanged())) dispose();
385    }//GEN-LAST:event_formWindowClosing
386
387    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
388        CommonSubs.compactDefaultTableModel(_mIL_TableOfExternalSignalNamesDefaultTableModel);
389    }//GEN-LAST:event_jButton1ActionPerformed
390
391    private void BT_ReplaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BT_ReplaceActionPerformed
392        int index = _mOS_NumberEntry.getSelectedIndex();
393        if (index != -1) { // Safety:
394            CodeButtonHandlerData otherCodeButtonHandlerData = _mCTCSerialData.getCodeButtonHandlerDataViaUniqueID(_mUniqueIDS.get(index));
395            loadUpSignalTable(ProjectsCommonSubs.getArrayListOfSignalNames(otherCodeButtonHandlerData._mIL_Signals));
396        }
397    }//GEN-LAST:event_BT_ReplaceActionPerformed
398
399    // Variables declaration - do not modify//GEN-BEGIN:variables
400    private javax.swing.JButton BT_Replace;
401    private javax.swing.JTable _mIL_TableOfExternalSignalNames;
402    private javax.swing.JComboBox<String> _mOS_NumberEntry;
403    private javax.swing.JButton _mSaveAndClose;
404    private javax.swing.JLabel _mTableOfSignalNamesPrompt;
405    private javax.swing.JButton jButton1;
406    private javax.swing.JLabel jLabel1;
407    private javax.swing.JLabel jLabel2;
408    private javax.swing.JLabel jLabel4;
409    private javax.swing.JLabel jLabel5;
410    private javax.swing.JLabel jLabel6;
411    private javax.swing.JScrollPane jScrollPane1;
412    // End of variables declaration//GEN-END:variables
413}