001package jmri.jmrit.conditional; 002 003import java.awt.Container; 004import java.awt.Dimension; 005import java.awt.FlowLayout; 006import java.awt.event.ActionEvent; 007import java.awt.event.ActionListener; 008import java.beans.PropertyChangeListener; 009import java.util.ArrayList; 010import java.util.List; 011 012import javax.swing.*; 013import javax.swing.border.Border; 014import javax.swing.table.*; 015 016import jmri.*; 017import jmri.jmrit.sensorgroup.SensorGroupFrame; 018import jmri.util.JmriJFrame; 019import jmri.util.swing.JmriJOptionPane; 020import jmri.util.table.ButtonEditor; 021import jmri.util.table.ButtonRenderer; 022 023/** 024 * The traditional list based conditional editor based on the original editor 025 * included in LogixTableAction. 026 * <p> 027 * Conditionals now have two policies to trigger execution of their action 028 * lists: 029 * <ol> 030 * <li>the previous policy - Trigger on change of state only 031 * <li>the new default - Trigger on any enabled state calculation 032 * </ol> 033 * Jan 15, 2011 - Pete Cressman 034 * <p> 035 * Two additional action and variable name selection methods have been added: 036 * <ol> 037 * <li>Single Pick List 038 * <li>Combo Box Selection 039 * </ol> 040 * The traditional tabbed Pick List with text entry is the default method. 041 * The Options menu has been expanded to list the 3 methods. 042 * Mar 27, 2017 - Dave Sand 043 * <p> 044 * Add a Browse Option to the Logix Select Menu. This will display a window that 045 * creates a formatted list of the contents of the selected Logix with each 046 * Conditional, Variable and Action. The code is courtesy of Chuck Catania and 047 * is used with his permission. Apr 2, 2017 - Dave Sand 048 * <p> 049 * Compare with the other Conditional Edit tool {@link ConditionalTreeEdit} 050 * 051 * @author Dave Duchamp Copyright (C) 2007 052 * @author Pete Cressman Copyright (C) 2009, 2010, 2011 053 * @author Matthew Harris copyright (c) 2009 054 * @author Dave Sand copyright (c) 2017 055 */ 056public class ConditionalListEdit extends ConditionalList { 057 058 /** 059 * Create a new Conditional List View editor. 060 * 061 * @param sName name of the Logix being edited 062 */ 063 public ConditionalListEdit(String sName) { 064 super(sName); 065 makeEditLogixWindow(); 066 } 067 068 public ConditionalListEdit() { 069 } 070 071 // ------------ Logix Variables ------------ 072 JTextField _editUserName; 073 JLabel _status; 074 int _numConditionals = 0; 075 076 // ------------ Conditional Variables ------------ 077 ConditionalTableModel conditionalTableModel = null; 078 int _conditionalRowNumber = 0; 079 boolean _inReorderMode = false; 080 int _nextInOrder = 0; 081 082 static final int STRUT = 10; 083 084 // ------------ Methods for Edit Logix Pane ------------ 085 086 /** 087 * Create and/or initialize the Edit Logix pane. 088 */ 089 void makeEditLogixWindow() { 090 _editUserName = new JTextField(20); 091 _editUserName.setText(_curLogix.getUserName()); 092 // clear conditional table if needed 093 if (conditionalTableModel != null) { 094 conditionalTableModel.fireTableStructureChanged(); 095 } 096 _inEditMode = true; 097 if (_editLogixFrame == null) { 098 _editLogixFrame = new JmriJFrame(Bundle.getMessage("TitleEditLogix"), false, false); // NOI18N 099 _editLogixFrame.addHelpMenu( 100 "package.jmri.jmrit.conditional.ConditionalListEditor", true); // NOI18N 101 _editLogixFrame.setLocation(100, 30); 102 Container contentPane = _editLogixFrame.getContentPane(); 103 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 104 JPanel panel1 = new JPanel(); 105 panel1.setLayout(new FlowLayout()); 106 JLabel systemNameLabel = new JLabel(Bundle.getMessage("ColumnSystemName") + ":"); // NOI18N 107 panel1.add(systemNameLabel); 108 JLabel fixedSystemName = new JLabel(_curLogix.getSystemName()); 109 panel1.add(fixedSystemName); 110 contentPane.add(panel1); 111 JPanel panel2 = new JPanel(); 112 panel2.setLayout(new FlowLayout()); 113 JLabel userNameLabel = new JLabel(Bundle.getMessage("ColumnUserName") + ":"); // NOI18N 114 panel2.add(userNameLabel); 115 panel2.add(_editUserName); 116 _editUserName.setToolTipText(Bundle.getMessage("LogixUserNameHint2")); // NOI18N 117 contentPane.add(panel2); 118 // add table of Conditionals 119 JPanel pctSpace = new JPanel(); 120 pctSpace.setLayout(new FlowLayout()); 121 pctSpace.add(new JLabel(" ")); 122 contentPane.add(pctSpace); 123 JPanel pTitle = new JPanel(); 124 pTitle.setLayout(new FlowLayout()); 125 pTitle.add(new JLabel(Bundle.getMessage("ConditionalTableTitle"))); // NOI18N 126 contentPane.add(pTitle); 127 // initialize table of conditionals 128 conditionalTableModel = new ConditionalTableModel(); 129 JTable conditionalTable = new JTable(conditionalTableModel); 130 conditionalTable.setRowSelectionAllowed(false); 131 TableColumnModel conditionalColumnModel = conditionalTable 132 .getColumnModel(); 133 TableColumn sNameColumn = conditionalColumnModel 134 .getColumn(ConditionalTableModel.SNAME_COLUMN); 135 sNameColumn.setResizable(true); 136 sNameColumn.setMinWidth(100); 137 sNameColumn.setPreferredWidth(130); 138 TableColumn uNameColumn = conditionalColumnModel 139 .getColumn(ConditionalTableModel.UNAME_COLUMN); 140 uNameColumn.setResizable(true); 141 uNameColumn.setMinWidth(210); 142 uNameColumn.setPreferredWidth(260); 143 TableColumn stateColumn = conditionalColumnModel 144 .getColumn(ConditionalTableModel.STATE_COLUMN); 145 stateColumn.setResizable(true); 146 stateColumn.setMinWidth(50); 147 stateColumn.setMaxWidth(100); 148 TableColumn buttonColumn = conditionalColumnModel 149 .getColumn(ConditionalTableModel.BUTTON_COLUMN); 150 151 // install button renderer and editor 152 ButtonRenderer buttonRenderer = new ButtonRenderer(); 153 conditionalTable.setDefaultRenderer(JButton.class, buttonRenderer); 154 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 155 conditionalTable.setDefaultEditor(JButton.class, buttonEditor); 156 JButton testButton = new JButton("XXXXXX"); // NOI18N 157 conditionalTable.setRowHeight(testButton.getPreferredSize().height); 158 buttonColumn.setMinWidth(testButton.getPreferredSize().width); 159 buttonColumn.setMaxWidth(testButton.getPreferredSize().width); 160 buttonColumn.setResizable(false); 161 162 JScrollPane conditionalTableScrollPane = new JScrollPane(conditionalTable); 163 Dimension dim = conditionalTable.getPreferredSize(); 164 dim.height = 450; 165 conditionalTableScrollPane.getViewport().setPreferredSize(dim); 166 contentPane.add(conditionalTableScrollPane); 167 168 // add message area between table and buttons 169 JPanel panel4 = new JPanel(); 170 panel4.setLayout(new BoxLayout(panel4, BoxLayout.Y_AXIS)); 171 JPanel panel41 = new JPanel(); 172 panel41.setLayout(new FlowLayout()); 173 _status = new JLabel(" "); 174 panel41.add(_status); 175 panel4.add(panel41); 176 JPanel panel42 = new JPanel(); 177 panel42.setLayout(new FlowLayout()); 178 // Conditional panel buttons - New Conditional 179 JButton newConditionalButton = new JButton(Bundle.getMessage("NewConditionalButton")); // NOI18N 180 panel42.add(newConditionalButton); 181 newConditionalButton.addActionListener(new ActionListener() { 182 @Override 183 public void actionPerformed(ActionEvent e) { 184 newConditionalPressed(e); 185 } 186 }); 187 newConditionalButton.setToolTipText(Bundle.getMessage("NewConditionalButtonHint")); // NOI18N 188 // Conditional panel buttons - Reorder 189 JButton reorderButton = new JButton(Bundle.getMessage("ReorderButton")); // NOI18N 190 panel42.add(reorderButton); 191 reorderButton.addActionListener(new ActionListener() { 192 @Override 193 public void actionPerformed(ActionEvent e) { 194 reorderPressed(e); 195 } 196 }); 197 reorderButton.setToolTipText(Bundle.getMessage("ReorderButtonHint")); // NOI18N 198 // Conditional panel buttons - Calculate 199 JButton calculateButton = new JButton(Bundle.getMessage("CalculateButton")); // NOI18N 200 panel42.add(calculateButton); 201 calculateButton.addActionListener(new ActionListener() { 202 @Override 203 public void actionPerformed(ActionEvent e) { 204 calculatePressed(e); 205 } 206 }); 207 calculateButton.setToolTipText(Bundle.getMessage("CalculateButtonHint")); // NOI18N 208 panel4.add(panel42); 209 Border panel4Border = BorderFactory.createEtchedBorder(); 210 panel4.setBorder(panel4Border); 211 contentPane.add(panel4); 212 // add buttons at bottom of window 213 JPanel panel5 = new JPanel(); 214 panel5.setLayout(new FlowLayout()); 215 // Bottom Buttons - Done Logix 216 JButton done = new JButton(Bundle.getMessage("ButtonDone")); // NOI18N 217 panel5.add(done); 218 done.addActionListener(new ActionListener() { 219 @Override 220 public void actionPerformed(ActionEvent e) { 221 donePressed(e); 222 } 223 }); 224 done.setToolTipText(Bundle.getMessage("DoneButtonHint")); // NOI18N 225 // Delete Logix 226 JButton delete = new JButton(Bundle.getMessage("ButtonDelete")); // NOI18N 227 panel5.add(delete); 228 delete.addActionListener(new ActionListener() { 229 @Override 230 public void actionPerformed(ActionEvent e) { 231 deletePressed(e); 232 } 233 }); 234 delete.setToolTipText(Bundle.getMessage("DeleteLogixButtonHint")); // NOI18N 235 contentPane.add(panel5); 236 } 237 238 _editLogixFrame.addWindowListener(new java.awt.event.WindowAdapter() { 239 @Override 240 public void windowClosing(java.awt.event.WindowEvent e) { 241 donePressed(null); 242 } 243 }); 244 _editLogixFrame.pack(); 245 _editLogixFrame.setVisible(true); 246 } 247 248 /** 249 * Respond to the New Conditional Button in Edit Logix Window. 250 * 251 * @param e The event heard 252 */ 253 void newConditionalPressed(ActionEvent e) { 254 if (checkEditConditional()) { 255 return; 256 } 257 if (_curLogix.getSystemName().equals(SensorGroupFrame.logixSysName)) { 258 JmriJOptionPane.showMessageDialog(_editLogixFrame, 259 Bundle.getMessage("Warn8", SensorGroupFrame.logixUserName, SensorGroupFrame.logixSysName), 260 Bundle.getMessage("WarningTitle"), // NOI18N 261 JmriJOptionPane.WARNING_MESSAGE); 262 return; 263 } 264 _curConditional = makeNewConditional(_curLogix); 265 makeEditConditionalWindow(); 266 } 267 268 @Override 269 void updateConditionalTableModel() { 270 log.debug("updateConditionalTableModel"); 271 _numConditionals = _curLogix.getNumConditionals(); 272 conditionalTableModel.fireTableRowsInserted(_numConditionals, _numConditionals); 273 } 274 275 /** 276 * Respond to Edit Button in the Conditional table of the Edit Logix Window. 277 * 278 * @param rx index (row number) of Conditional to be edited 279 */ 280 void editConditionalPressed(int rx) { 281 if (checkEditConditional()) { 282 return; 283 } 284 // get Conditional to edit 285 _curConditional = _conditionalManager.getBySystemName(_curLogix.getConditionalByNumberOrder(rx)); 286 if (_curConditional == null) { 287 log.error("Attempted edit of non-existant conditional."); // NOI18N 288 return; 289 } 290 _conditionalRowNumber = rx; 291 makeEditConditionalWindow(); 292 } 293 294 /** 295 * Respond to the Reorder Button in the Edit Logix pane. 296 * 297 * @param e The event heard 298 */ 299 void reorderPressed(ActionEvent e) { 300 if (checkEditConditional()) { 301 return; 302 } 303 // Check if reorder is reasonable 304 _showReminder = true; 305 _nextInOrder = 0; 306 _inReorderMode = true; 307 _status.setText(Bundle.getMessage("ReorderMessage")); // NOI18N 308 conditionalTableModel.fireTableDataChanged(); 309 } 310 311 /** 312 * Responds to the Calculate Button in the Edit Logix window. 313 * 314 * @param e The event heard 315 */ 316 void calculatePressed(ActionEvent e) { 317 if (checkEditConditional()) { 318 return; 319 } 320 // are there Conditionals to calculate? 321 if (_numConditionals > 0) { 322 // There are conditionals to calculate 323 String cName = ""; 324 Conditional c = null; 325 for (int i = 0; i < _numConditionals; i++) { 326 cName = _curLogix.getConditionalByNumberOrder(i); 327 if (cName != null) { 328 c = _conditionalManager.getBySystemName(cName); 329 if (c == null) { 330 log.error("Invalid conditional system name when calculating - {}", cName); 331 } else { 332 // calculate without taking any action 333 c.calculate(false, null); 334 } 335 } else { 336 log.error("null conditional system name when calculating"); // NOI18N 337 } 338 } 339 // force the table to update 340 conditionalTableModel.fireTableDataChanged(); 341 } 342 } 343 344 /** 345 * Respond to the Done button in the Edit Logix window. 346 * <p> 347 * Note: We also get here if the Edit Logix window is dismissed, or if the 348 * Add button is pressed in the Logic Table with an active Edit Logix 349 * window. 350 * 351 * @param e The event heard 352 */ 353 void donePressed(ActionEvent e) { 354 if (checkEditConditional()) { 355 return; 356 } 357 if (_curLogix.getSystemName().equals(SensorGroupFrame.logixSysName)) { 358 finishDone(); 359 return; 360 } 361 // Check if the User Name has been changed 362 String uName = _editUserName.getText().trim(); 363 if (!(uName.equals(_curLogix.getUserName()))) { 364 // user name has changed - check if already in use 365 if (uName.length() > 0) { 366 Logix p = _logixManager.getByUserName(uName); 367 if (p != null) { 368 // Logix with this user name already exists 369 log.error("Failure to update Logix with Duplicate User Name: {}", uName); 370 JmriJOptionPane.showMessageDialog(_editLogixFrame, 371 Bundle.getMessage("Error6"), 372 Bundle.getMessage("ErrorTitle"), // NOI18N 373 JmriJOptionPane.ERROR_MESSAGE); 374 return; 375 } 376 } 377 // user name is unique, change it 378 // user name is unique, change it 379 logixData.clear(); 380 logixData.put("chgUname", uName); // NOI18N 381 fireLogixEvent(); 382 } 383 // complete update and activate Logix 384 finishDone(); 385 } 386 387 void finishDone() { 388 showSaveReminder(); 389 _inEditMode = false; 390 if (_editLogixFrame != null) { 391 _editLogixFrame.setVisible(false); 392 _editLogixFrame.dispose(); 393 _editLogixFrame = null; 394 } 395 logixData.clear(); 396 logixData.put("Finish", _curLogix.getSystemName()); // NOI18N 397 fireLogixEvent(); 398 } 399 400 /** 401 * Respond to the Delete button in the Edit Logix window. 402 * 403 * @param e The event heard 404 */ 405 void deletePressed(ActionEvent e) { 406 if (checkEditConditional()) { 407 return; 408 } 409 if (!checkConditionalReferences(_curLogix.getSystemName())) { 410 return; 411 } 412 _showReminder = true; 413 logixData.clear(); 414 logixData.put("Delete", _curLogix.getSystemName()); // NOI18N 415 fireLogixEvent(); 416 finishDone(); 417 } 418 419 /** 420 * Respond to the Delete Conditional Button in the Edit Conditional window. 421 */ 422 void deleteConditionalPressed() { 423 if (_curConditional == null) { 424 return; 425 } 426 String sName = _curConditional.getSystemName(); 427 428 if (!_newConditional) { 429 _showReminder = true; 430 _curConditional = null; 431 _numConditionals--; 432 loadReferenceNames(_conditionalFrame._variableList, _oldTargetNames); 433 String[] msgs = _curLogix.deleteConditional(sName); 434 if (msgs != null) { 435 JmriJOptionPane.showMessageDialog(_editLogixFrame, 436 Bundle.getMessage("Error11", (Object[]) msgs), // NOI18N 437 Bundle.getMessage("ErrorTitle"), 438 JmriJOptionPane.ERROR_MESSAGE); // NOI18N 439 } 440 conditionalTableModel.fireTableRowsDeleted(_conditionalRowNumber, 441 _conditionalRowNumber); 442 if (_numConditionals < 1 && !_suppressReminder) { 443 // warning message - last Conditional deleted 444 JmriJOptionPane.showMessageDialog(_editLogixFrame, 445 Bundle.getMessage("Warn1"), 446 Bundle.getMessage("WarningTitle"), // NOI18N 447 JmriJOptionPane.WARNING_MESSAGE); 448 } 449 } 450 _newConditional = false; 451 // complete deletion 452 if (_pickTables != null) { 453 _pickTables.dispose(); 454 _pickTables = null; 455 } 456 closeConditionalFrame(); 457 } 458 459 /** 460 * Check if edit of a conditional is in progress. 461 * 462 * @return true if this is the case, after showing dialog to user 463 */ 464 boolean checkEditConditional() { 465 if (_conditionalFrame != null) { 466 if (_conditionalFrame._dataChanged) { 467 // Already editing a Conditional, ask for completion of that edit 468 JmriJOptionPane.showMessageDialog(_conditionalFrame, 469 Bundle.getMessage("Error34", _curConditional.getSystemName()), // NOI18N 470 Bundle.getMessage("ErrorTitle"), // NOI18N 471 JmriJOptionPane.ERROR_MESSAGE); 472 return true; 473 } else { 474 _conditionalFrame.cancelConditionalPressed(); 475 } 476 } 477 return false; 478 } 479 480 // ============ Edit Conditional Window and Methods ============ 481 482 /** 483 * Create and/or initialize the Edit Conditional window. 484 * <p> 485 * Note: you can get here via the New Conditional button 486 * (newConditionalPressed) or via an Edit button in the Conditional table of 487 * the Edit Logix window. 488 */ 489 void makeEditConditionalWindow() { 490 // deactivate this Logix 491 _curLogix.deActivateLogix(); 492 493 _conditionalFrame = new ConditionalEditFrame(Bundle.getMessage("TitleEditConditional"), _curConditional, this); // NOI18N 494 _oldTargetNames.clear(); 495 loadReferenceNames(_conditionalFrame._variableList, _oldTargetNames); 496 497 _conditionalFrame.pack(); 498 _conditionalFrame.setVisible(true); 499 InstanceManager.getDefault(jmri.util.PlaceWindow.class).nextTo(_editLogixFrame, null, _conditionalFrame); 500 } 501 502 /** 503 * Make the bottom panel for _conditionalFrame to hold buttons for 504 * Update/Save, Cancel, Delete/FullEdit 505 * 506 * @return the panel 507 */ 508 @Override 509 JPanel makeBottomPanel() { 510 JPanel panel = new JPanel(); 511 512 JButton updateButton = new JButton(Bundle.getMessage("ButtonUpdate")); // NOI18N 513 panel.add(updateButton); 514 updateButton.addActionListener(new ActionListener() { 515 @Override 516 public void actionPerformed(ActionEvent e) { 517 _conditionalFrame.updateConditionalPressed(e); 518 } 519 }); 520 updateButton.setToolTipText(Bundle.getMessage("UpdateConditionalButtonHint")); // NOI18N 521 // Cancel 522 JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); // NOI18N 523 panel.add(cancelButton); 524 cancelButton.addActionListener(new ActionListener() { 525 @Override 526 public void actionPerformed(ActionEvent e) { 527 _conditionalFrame.cancelConditionalPressed(); 528 } 529 }); 530 cancelButton.setToolTipText(Bundle.getMessage("CancelConditionalButtonHint")); // NOI18N 531 532 // add Delete Conditional button to bottom panel 533 JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); // NOI18N 534 panel.add(deleteButton); 535 deleteButton.addActionListener(new ActionListener() { 536 @Override 537 public void actionPerformed(ActionEvent e) { 538 deleteConditionalPressed(); 539 } 540 }); 541 deleteButton.setToolTipText(Bundle.getMessage("DeleteConditionalButtonHint")); // NOI18N 542 543 return panel; 544 } 545 546 @Override 547 boolean updateConditional(String uName, Conditional.AntecedentOperator logicType, boolean trigger, String antecedent) { 548 log.debug("updateConditional"); 549 return super.updateConditional(uName, _curLogix, logicType, trigger, antecedent); 550 } 551 552 @Override 553 void closeConditionalFrame() { 554 log.debug("closeConditionalFrame()"); 555 conditionalTableModel.fireTableDataChanged(); 556 super.closeConditionalFrame(_curLogix); 557 } 558 559 boolean checkConditionalUserName(String uName) { 560 if ((uName != null) && (!(uName.equals("")))) { 561 Conditional p = _conditionalManager.getByUserName(_curLogix, uName); 562 if (p != null) { 563 // Conditional with this user name already exists 564 log.error("Failure to update Conditional with Duplicate User Name: {}", uName); 565 JmriJOptionPane.showMessageDialog(_conditionalFrame, 566 Bundle.getMessage("Error10"), // NOI18N 567 Bundle.getMessage("ErrorTitle"), // NOI18N 568 JmriJOptionPane.ERROR_MESSAGE); 569 return false; 570 } 571 } // else return false; 572 return true; 573 } 574 575 /** 576 * Respond to the First/Next (Delete/Reorder) Button in the ConditionalTableModel. 577 * 578 * @param row index of the row to put as next in line (instead of the one 579 * that was supposed to be next) 580 */ 581 void swapConditional(int row) { 582 _curLogix.swapConditional(_nextInOrder, row); 583 _nextInOrder++; 584 if (_nextInOrder >= _numConditionals) { 585 _inReorderMode = false; 586 } 587 //status.setText(""); 588 conditionalTableModel.fireTableDataChanged(); 589 } 590 591 /** 592 * Table model for Conditionals in the Edit Logix pane. 593 */ 594 public class ConditionalTableModel extends AbstractTableModel implements 595 PropertyChangeListener { 596 597 public static final int SNAME_COLUMN = 0; 598 599 public static final int UNAME_COLUMN = 1; 600 601 public static final int STATE_COLUMN = 2; 602 603 public static final int BUTTON_COLUMN = 3; 604 605 public ConditionalTableModel() { 606 super(); 607 _conditionalManager.addPropertyChangeListener(this); 608 updateConditionalListeners(); 609 } 610 611 synchronized void updateConditionalListeners() { 612 // first, remove listeners from the individual objects 613 String sNam = ""; 614 Conditional c = null; 615 _numConditionals = _curLogix.getNumConditionals(); 616 for (int i = 0; i < _numConditionals; i++) { 617 // if object has been deleted, it's not here; ignore it 618 sNam = _curLogix.getConditionalByNumberOrder(i); 619 c = _conditionalManager.getBySystemName(sNam); 620 if (c != null) { 621 c.removePropertyChangeListener(this); 622 } 623 } 624 // and add them back in 625 for (int i = 0; i < _numConditionals; i++) { 626 sNam = _curLogix.getConditionalByNumberOrder(i); 627 c = _conditionalManager.getBySystemName(sNam); 628 if (c != null) { 629 c.addPropertyChangeListener(this); 630 } 631 } 632 } 633 634 @Override 635 public void propertyChange(java.beans.PropertyChangeEvent e) { 636 if (e.getPropertyName().equals("length")) { // NOI18N 637 // a new NamedBean is available in the manager 638 updateConditionalListeners(); 639 fireTableDataChanged(); 640 } else if (matchPropertyName(e)) { 641 // a value changed. 642 fireTableDataChanged(); 643 } 644 } 645 646 /** 647 * Check if this property event is announcing a change this table should 648 * display. 649 * <p> 650 * Note that events will come both from the NamedBeans and from the 651 * manager. 652 * 653 * @param e the event heard 654 * @return true if a change in State or Appearance was heard 655 */ 656 boolean matchPropertyName(java.beans.PropertyChangeEvent e) { 657 return (e.getPropertyName().contains("State") || // NOI18N 658 e.getPropertyName().contains("Appearance")); // NOI18N 659 } 660 661 @Override 662 public Class<?> getColumnClass(int c) { 663 if (c == BUTTON_COLUMN) { 664 return JButton.class; 665 } 666 return String.class; 667 } 668 669 @Override 670 public int getColumnCount() { 671 return 4; 672 } 673 674 @Override 675 public int getRowCount() { 676 return (_numConditionals); 677 } 678 679 @Override 680 public boolean isCellEditable(int r, int c) { 681 if (!_inReorderMode) { 682 return ((c == UNAME_COLUMN) || (c == BUTTON_COLUMN)); 683 } else if (c == BUTTON_COLUMN) { 684 return (r >= _nextInOrder); 685 } 686 return false; 687 } 688 689 @Override 690 public String getColumnName(int col) { 691 switch (col) { 692 case SNAME_COLUMN: 693 return Bundle.getMessage("ColumnSystemName"); // NOI18N 694 case UNAME_COLUMN: 695 return Bundle.getMessage("ColumnUserName"); // NOI18N 696 case BUTTON_COLUMN: 697 return ""; // no label 698 case STATE_COLUMN: 699 return Bundle.getMessage("ColumnState"); // NOI18N 700 default: 701 return ""; 702 } 703 } 704 705 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", 706 justification = "better to keep cases in column order rather than to combine") 707 public int getPreferredWidth(int col) { 708 switch (col) { 709 case SNAME_COLUMN: 710 case BUTTON_COLUMN: 711 return new JTextField(6).getPreferredSize().width; 712 case UNAME_COLUMN: 713 return new JTextField(17).getPreferredSize().width; 714 case STATE_COLUMN: 715 return new JTextField(12).getPreferredSize().width; 716 default: 717 return new JTextField(5).getPreferredSize().width; 718 } 719 } 720 721 @Override 722 public Object getValueAt(int row, int col) { 723 if ((row > _numConditionals) || (_curLogix == null)) { 724 return null; 725 } 726 switch (col) { 727 case BUTTON_COLUMN: 728 if (!_inReorderMode) { 729 return Bundle.getMessage("ButtonEdit"); // NOI18N 730 } else if (_nextInOrder == 0) { 731 return Bundle.getMessage("ButtonFirst"); // NOI18N 732 } else if (_nextInOrder <= row) { 733 return Bundle.getMessage("ButtonNext"); // NOI18N 734 } else { 735 return Integer.toString(row + 1); 736 } 737 case SNAME_COLUMN: 738 return _curLogix.getConditionalByNumberOrder(row); 739 case UNAME_COLUMN: { 740 //log.debug("ConditionalTableModel: {}", _curLogix.getConditionalByNumberOrder(row)); // NOI18N 741 Conditional c = _conditionalManager.getBySystemName( 742 _curLogix.getConditionalByNumberOrder(row)); 743 if (c != null) { 744 return c.getUserName(); 745 } 746 return ""; 747 } 748 case STATE_COLUMN: 749 Conditional c = _conditionalManager.getBySystemName( 750 _curLogix.getConditionalByNumberOrder(row)); 751 if (c != null) { 752 int curState = c.getState(); 753 if (curState == Conditional.TRUE) { 754 return Bundle.getMessage("True"); // NOI18N 755 } 756 if (curState == Conditional.FALSE) { 757 return Bundle.getMessage("False"); // NOI18N 758 } 759 } 760 return Bundle.getMessage("BeanStateUnknown"); // NOI18N 761 default: 762 return Bundle.getMessage("BeanStateUnknown"); // NOI18N 763 } 764 } 765 766 @Override 767 public void setValueAt(Object value, int row, int col) { 768 if ((row > _numConditionals) || (_curLogix == null)) { 769 return; 770 } 771 if (col == BUTTON_COLUMN) { 772 if (_inReorderMode) { 773 swapConditional(row); 774 } else if (_curLogix.getSystemName().equals(SensorGroupFrame.logixSysName)) { 775 JmriJOptionPane.showMessageDialog(_conditionalFrame, 776 Bundle.getMessage("Warn8", SensorGroupFrame.logixUserName, SensorGroupFrame.logixSysName), 777 Bundle.getMessage("WarningTitle"), 778 JmriJOptionPane.WARNING_MESSAGE); // NOI18N 779 } else { 780 // Use separate Runnable so window is created on top 781 class WindowMaker implements Runnable { 782 783 private int _row; 784 785 WindowMaker(int r) { 786 _row = r; 787 } 788 789 @Override 790 public void run() { 791 editConditionalPressed(_row); 792 } 793 } 794 WindowMaker t = new WindowMaker(row); 795 javax.swing.SwingUtilities.invokeLater(t); 796 } 797 } else if (col == UNAME_COLUMN) { 798 String uName = (String) value; 799 Conditional cn = _conditionalManager.getByUserName(_curLogix, uName); 800 if (cn == null) { 801 String sName = _curLogix.getConditionalByNumberOrder(row); 802 Conditional cdl = _conditionalManager.getBySystemName(sName); 803 if (cdl==null){ 804 log.error("No conditional {} while editing user name",sName); 805 return; 806 } 807 cdl.setUserName(uName); 808 fireTableRowsUpdated(row, row); 809 810 // Update any conditional references 811 ArrayList<String> refList = InstanceManager.getDefault(jmri.ConditionalManager.class).getWhereUsed(sName); 812 if (refList != null) { 813 for (String ref : refList) { 814 Conditional cRef = _conditionalManager.getBySystemName(ref); 815 if (cRef==null){ 816 continue; 817 } 818 List<ConditionalVariable> varList = cRef.getCopyOfStateVariables(); 819 for (ConditionalVariable var : varList) { 820 // Find the affected conditional variable 821 if (var.getName().equals(sName)) { 822 var.setGuiName( (uName.length() > 0) ? uName : sName ); 823 } 824 } 825 cRef.setStateVariables(varList); 826 } 827 } 828 } else { 829 // Duplicate user name 830 String svName = _curLogix.getConditionalByNumberOrder(row); 831 if (cn != _conditionalManager.getBySystemName(svName)) { 832 messageDuplicateConditionalUserName(cn.getSystemName()); 833 } 834 } 835 } 836 } 837 } 838 839 840 @Override 841 protected String getClassName() { 842 return ConditionalListEdit.class.getName(); 843 } 844 845 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConditionalListEdit.class); 846 847}