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}