001package jmri.jmrit.beantable; 002 003import java.awt.BorderLayout; 004import java.awt.Component; 005import java.awt.Container; 006import java.awt.FlowLayout; 007import java.awt.event.ActionEvent; 008import java.beans.PropertyChangeListener; 009import java.util.*; 010import javax.annotation.Nonnull; 011import javax.swing.*; 012import javax.swing.table.AbstractTableModel; 013import javax.swing.table.TableColumn; 014import javax.swing.table.TableColumnModel; 015import jmri.Conditional.Operator; 016import jmri.*; 017import jmri.implementation.DefaultConditionalAction; 018import jmri.script.swing.ScriptFileChooser; 019import jmri.util.FileUtil; 020import jmri.util.JmriJFrame; 021 022/** 023 * Swing action to create and register groups of Logix Condtionals to perform a 024 * railroad control task. 025 * 026 * @author Pete Cressman Copyright (C) 2009 027 * @author Egbert Broerse i18n 2016 028 * 029 */ 030public class LRouteTableAction extends AbstractTableAction<Logix> { 031 032 static final ResourceBundle rbx = ResourceBundle.getBundle("jmri.jmrit.beantable.LRouteTableBundle"); 033 034 /** 035 * Create an action with a specific title. 036 * <p> 037 * Note that the argument is the Action title, not the title of the 038 * resulting frame. Perhaps this should be changed? 039 * 040 * @param s title of the action 041 */ 042 public LRouteTableAction(String s) { 043 super(s); 044 _logixManager = InstanceManager.getNullableDefault(jmri.LogixManager.class); 045 _conditionalManager = InstanceManager.getNullableDefault(jmri.ConditionalManager.class); 046 // disable ourself if there is no Logix manager or no Conditional manager available 047 if ((_logixManager == null) || (_conditionalManager == null)) { 048 setEnabled(false); 049 } 050 createModel(); 051 } 052 053 public LRouteTableAction() { 054 this(Bundle.getMessage("TitleLRouteTable")); 055 } 056 057 /** 058 * Create the JTable DataModel, along with the changes for the specific case 059 * of Road Conditionals. 060 */ 061 @Override 062 protected void createModel() { 063 m = new LBeanTableDataModel(); 064 } 065 066 class LBeanTableDataModel extends BeanTableDataModel<Logix> { 067 068 // overlay the state column with the edit column 069 static public final int ENABLECOL = VALUECOL; 070 static public final int EDITCOL = DELETECOL; 071 protected String enabledString = Bundle.getMessage("ColumnHeadEnabled"); 072 073 /** 074 * Override to filter out the LRoutes from the rest of Logix. 075 */ 076 @Override 077 protected synchronized void updateNameList() { 078 // first, remove listeners from the individual objects 079 if (sysNameList != null) { 080 for (int i = 0; i < sysNameList.size(); i++) { 081 // if object has been deleted, it's not here; ignore it 082 NamedBean b = getBySystemName(sysNameList.get(i)); 083 if (b != null) { 084 b.removePropertyChangeListener(this); 085 } 086 } 087 } 088 sysNameList = new ArrayList<>(); 089 // and add them back in 090 getManager().getNamedBeanSet().forEach(b -> { 091 if (b.getSystemName().startsWith(getLogixSystemPrefix())) { 092 sysNameList.add(b.getSystemName()); 093 b.addPropertyChangeListener(this); 094 } 095 }); 096 log.debug("updateNameList: sysNameList size= {}", sysNameList.size()); 097 } 098 099 @Override 100 public String getColumnName(int col) { 101 switch (col) { 102 case EDITCOL: 103 return ""; // no heading on "Edit" 104 case ENABLECOL: 105 return enabledString; 106 default: 107 return super.getColumnName(col); 108 } 109 } 110 111 @Override 112 public Class<?> getColumnClass(int col) { 113 switch (col) { 114 case EDITCOL: 115 return JButton.class; 116 case ENABLECOL: 117 return Boolean.class; 118 default: 119 return super.getColumnClass(col); 120 } 121 } 122 123 @Override 124 public int getPreferredWidth(int col) { 125 // override default value for SystemName and UserName columns 126 switch (col) { 127 case SYSNAMECOL: 128 return new JTextField(20).getPreferredSize().width; 129 case USERNAMECOL: 130 case COMMENTCOL: 131 return new JTextField(25).getPreferredSize().width; 132 case EDITCOL: 133 // not actually used due to the configDeleteColumn, setColumnToHoldButton, configureButton 134 return new JTextField(Bundle.getMessage("ButtonEdit")).getPreferredSize().width+4; 135 case ENABLECOL: 136 // not actually used due to the configValueColumn, setColumnToHoldButton, configureButton 137 return new JTextField(5).getPreferredSize().width; 138 default: 139 return super.getPreferredWidth(col); 140 } 141 } 142 143 @Override 144 public boolean isCellEditable(int row, int col) { 145 switch (col) { 146 case EDITCOL: 147 case ENABLECOL: 148 return true; 149 default: 150 return super.isCellEditable(row, col); 151 } 152 } 153 154 @Override 155 public Object getValueAt(int row, int col) { 156 switch (col) { 157 case EDITCOL: 158 return Bundle.getMessage("ButtonEdit"); 159 case ENABLECOL: 160 return ((Logix) getValueAt(row, SYSNAMECOL)).getEnabled(); 161 default: 162 return super.getValueAt(row, col); 163 } 164 } 165 166 @Override 167 public void setValueAt(Object value, int row, int col) { 168 switch (col) { 169 case EDITCOL: 170 // set up to edit 171 String sName = ((Logix) getValueAt(row, SYSNAMECOL)).getSystemName(); 172 editPressed(sName); 173 break; 174 case ENABLECOL: 175 // alternate 176 Logix x = (Logix) getValueAt(row, SYSNAMECOL); 177 boolean v = x.getEnabled(); 178 x.setEnabled(!v); 179 break; 180 default: 181 super.setValueAt(value, row, col); 182 break; 183 } 184 } 185 186 /** 187 * Delete the bean after all the checking has been done. 188 * <p> 189 * Deactivate the Logix and remove its conditionals. 190 */ 191 @Override 192 protected void doDelete(Logix logix) { 193 if (logix != null) { 194 logix.deActivateLogix(); 195 // delete the Logix and all its Conditionals 196 _logixManager.deleteLogix(logix); 197 } 198 } 199 200 @Override 201 protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) { 202 if (e.getPropertyName().equals(enabledString)) { 203 return true; 204 } else { 205 return super.matchPropertyName(e); 206 } 207 } 208 209 @Override 210 public Manager<Logix> getManager() { 211 return _logixManager; 212 } 213 214 @Override 215 public Logix getBySystemName(@Nonnull String name) { 216 return _logixManager.getBySystemName(name); 217 } 218 219 @Override 220 public Logix getByUserName(@Nonnull String name) { 221 return _logixManager.getByUserName(name); 222 } 223 224 /*public int getDisplayDeleteMsg() { return InstanceManager.getDefault(jmri.UserPreferencesManager.class).getMultipleChoiceOption(getClassName(),"delete"); } 225 public void setDisplayDeleteMsg(int boo) { InstanceManager.getDefault(jmri.UserPreferencesManager.class).setMultipleChoiceOption(getClassName(), "delete", boo); }*/ 226 @Override 227 protected String getMasterClassName() { 228 return getClassName(); 229 } 230 231 @Override 232 public void configureTable(JTable table) { 233 table.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer()); 234 table.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer()); 235 table.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor()); 236 super.configureTable(table); 237 } 238 239 // Not needed - here for interface compatibility 240 @Override 241 public void clickOn(Logix t) { 242 } 243 244 @Override 245 public String getValue(String s) { 246 return ""; 247 } 248 249 // typical to get correct width 250 @Override 251 protected void configDeleteColumn(JTable table) { 252 // have the DELETECOL = EDITCOL column hold a button 253 setColumnToHoldButton(table, DELETECOL, 254 new JButton(Bundle.getMessage("ButtonEdit"))); 255 } 256 257 @Override 258 protected void configValueColumn(JTable table) { 259 } 260 261 @Override 262 protected String getBeanType() { 263 return "LRoute"; 264 } 265 266 } 267 268 @Override 269 protected void setTitle() { 270 f.setTitle(Bundle.getMessage("TitleLRouteTable")); 271 } 272 273 @Override 274 protected String helpTarget() { 275 return "package.jmri.jmrit.beantable.LRouteTable"; 276 } 277 278///////////////////////////////////// Edit window ////////////////////////////// 279 ConditionalManager _conditionalManager = null; 280 LogixManager _logixManager = null; 281 282 JTextField _systemName = new JTextField(15); 283 JTextField _userName = new JTextField(25); 284 285 JmriJFrame _addFrame = null; 286 JTabbedPane _tabbedPane = null; 287 288 RouteInputModel _inputModel; 289 JScrollPane _inputScrollPane; 290 JComboBox<String> _testStateCombo; 291 JRadioButton _inputAllButton; 292 boolean _showAllInput; 293 294 RouteOutputModel _outputModel; 295 JScrollPane _outputScrollPane; 296 JComboBox<String> _setStateCombo; 297 JRadioButton _outputAllButton; 298 boolean _showAllOutput; 299 300 AlignmentModel _alignModel; 301 JComboBox<String> _alignCombo; 302 JRadioButton _alignAllButton; 303 boolean _showAllAlign; 304 305 JCheckBox _lockCheckBox; 306 boolean _lock = false; 307 308 JPanel _typePanel; 309 JRadioButton _newRouteButton; 310 boolean _newRouteType = true; 311 JRadioButton _initializeButton; 312 boolean _initialize = false; 313 314 JTextField soundFile = new JTextField(30); 315 JTextField scriptFile = new JTextField(30); 316 317 JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); 318 JButton createButton = new JButton(Bundle.getMessage("ButtonCreate")); 319 JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 320 JButton updateButton = new JButton(Bundle.getMessage("ButtonUpdate")); 321 322 boolean routeDirty = false; // true to fire reminder to save work 323 private boolean checkEnabled = jmri.InstanceManager.getDefault(jmri.configurexml.ShutdownPreferences.class).isStoreCheckEnabled(); 324 325 ArrayList<RouteInputElement> _inputList; 326 private HashMap<String, RouteInputElement> _inputMap; 327 private HashMap<String, RouteInputElement> _inputUserMap; 328 private ArrayList<RouteInputElement> _includedInputList; 329 330 ArrayList<RouteOutputElement> _outputList; 331 private HashMap<String, RouteOutputElement> _outputMap; 332 private HashMap<String, RouteOutputElement> _outputUserMap; 333 private ArrayList<RouteOutputElement> _includedOutputList; 334 335 ArrayList<AlignElement> _alignList; 336 private HashMap<String, AlignElement> _alignMap; 337 private HashMap<String, AlignElement> _alignUserMap; 338 private ArrayList<AlignElement> _includedAlignList; 339 340 void buildLists() { 341 TreeSet<RouteInputElement> inputTS = new TreeSet<>(new RouteElementComparator()); 342 TreeSet<RouteOutputElement> outputTS = new TreeSet<>(new RouteElementComparator()); 343 //TreeSet <RouteInputElement>inputTS = new TreeSet<RouteInputElement>(); 344 //TreeSet <RouteOutputElement>outputTS = new TreeSet<RouteOutputElement>(); 345 jmri.TurnoutManager tm = InstanceManager.turnoutManagerInstance(); 346 tm.getNamedBeanSet().forEach((nb) -> { 347 String userName = nb.getUserName(); 348 String systemName = nb.getSystemName(); 349 inputTS.add(new RouteInputTurnout(systemName, userName)); 350 outputTS.add(new RouteOutputTurnout(systemName, userName)); 351 }); 352 353 TreeSet<AlignElement> alignTS = new TreeSet<>(new RouteElementComparator()); 354 jmri.SensorManager sm = InstanceManager.sensorManagerInstance(); 355 sm.getNamedBeanSet().forEach((nb) -> { 356 String userName = nb.getUserName(); 357 String systemName = nb.getSystemName(); 358 inputTS.add(new RouteInputSensor(systemName, userName)); 359 outputTS.add(new RouteOutputSensor(systemName, userName)); 360 alignTS.add(new AlignElement(systemName, userName)); 361 }); 362 jmri.LightManager lm = InstanceManager.lightManagerInstance(); 363 lm.getNamedBeanSet().forEach((nb) -> { 364 String userName = nb.getUserName(); 365 String systemName = nb.getSystemName(); 366 inputTS.add(new RouteInputLight(systemName, userName)); 367 outputTS.add(new RouteOutputLight(systemName, userName)); 368 }); 369 jmri.SignalHeadManager shm = InstanceManager.getDefault(jmri.SignalHeadManager.class); 370 shm.getNamedBeanSet().forEach((nb) -> { 371 String userName = nb.getUserName(); 372 String systemName = nb.getSystemName(); 373 inputTS.add(new RouteInputSignal(systemName, userName)); 374 outputTS.add(new RouteOutputSignal(systemName, userName)); 375 }); 376 _includedInputList = new ArrayList<>(); 377 _includedOutputList = new ArrayList<>(); 378 _inputList = new ArrayList<>(inputTS.size()); 379 _outputList = new ArrayList<>(outputTS.size()); 380 _inputMap = new HashMap<>(inputTS.size()); 381 _outputMap = new HashMap<>(outputTS.size()); 382 _inputUserMap = new HashMap<>(); 383 _outputUserMap = new HashMap<>(); 384 Iterator<RouteInputElement> it = inputTS.iterator(); 385 while (it.hasNext()) { 386 RouteInputElement elt = it.next(); 387 _inputList.add(elt); 388 String key = elt.getType() + elt.getSysName(); 389 _inputMap.put(key, elt); 390 String user = elt.getUserName(); 391 if (user != null) { 392 key = elt.getType() + user; 393 _inputUserMap.put(key, elt); 394 } 395 } 396 Iterator<RouteOutputElement> itOut = outputTS.iterator(); 397 while (itOut.hasNext()) { 398 RouteOutputElement elt = itOut.next(); 399 _outputList.add(elt); 400 String key = elt.getType() + elt.getSysName(); 401 _outputMap.put(key, elt); 402 String user = elt.getUserName(); 403 if (user != null) { 404 key = elt.getType() + user; 405 _outputUserMap.put(key, elt); 406 } 407 } 408 _includedAlignList = new ArrayList<>(); 409 _alignList = new ArrayList<>(alignTS.size()); 410 _alignMap = new HashMap<>(alignTS.size()); 411 _alignUserMap = new HashMap<>(); 412 Iterator<AlignElement> itAlign = alignTS.iterator(); 413 while (itAlign.hasNext()) { 414 AlignElement elt = itAlign.next(); 415 _alignList.add(elt); 416 String key = elt.getType() + elt.getSysName(); 417 _alignMap.put(key, elt); 418 String user = elt.getUserName(); 419 if (user != null) { 420 key = elt.getType() + user; 421 _alignUserMap.put(key, elt); 422 } 423 } 424 } 425 426 /** 427 * Edit button in Logix Route table pressed. 428 * 429 * @param sName system name of Logix to edit 430 */ 431 void editPressed(String sName) { 432 // Logix was found, initialize for edit 433 Logix logix = _logixManager.getBySystemName(sName); 434 if (logix == null) { 435 log.error("Logix \"{}\" not Found.", sName); 436 return; 437 } 438 // deactivate this Logix 439 _systemName.setText(sName); 440 // create the Edit Logix Window 441 // Use separate Runnable so window is created on top 442 Runnable t = () -> { 443 setupEdit(null); 444 _addFrame.setVisible(true); 445 }; 446 javax.swing.SwingUtilities.invokeLater(t); 447 } 448 449 /** 450 * Interprets the conditionals from the Logix that was selected for editing 451 * and attempts to reconstruct the window entries. 452 * 453 * @param e the action event 454 */ 455 void setupEdit(ActionEvent e) { 456 makeEditWindow(); 457 Logix logix = checkNamesOK(); 458 if (logix == null) { 459 return; 460 } 461 logix.deActivateLogix(); 462 // get information for this route 463 _systemName.setEnabled(false); 464 _userName.setEnabled(false); 465 _systemName.setText(logix.getSystemName()); 466 _userName.setText(logix.getUserName()); 467 String logixSysName = logix.getSystemName(); 468 int numConditionals = logix.getNumConditionals(); 469 log.debug("setupEdit: logixSysName= {}, numConditionals= {}", logixSysName, numConditionals); 470 for (int i = 0; i < numConditionals; i++) { 471 String cSysName = logix.getConditionalByNumberOrder(i); 472 switch (getRouteConditionalType(logixSysName, cSysName)) { 473 case 'T': 474 getControlsAndActions(cSysName); 475 break; 476 case 'A': 477 getAlignmentSensors(cSysName); 478 break; 479 case 'L': 480 getLockConditions(cSysName); 481 break; 482 default: 483 log.warn("Unexpected getRouteConditionalType {}", getRouteConditionalType(logixSysName, cSysName)); 484 break; 485 } 486 } 487 // set up buttons and notes 488 deleteButton.setVisible(true); 489 cancelButton.setVisible(true); 490 updateButton.setVisible(true); 491 _typePanel.setVisible(false); 492 _initialize = getLogixInitializer().equals(logixSysName); 493 if (_initialize) { 494 _initializeButton.doClick(); 495 } else { 496 _newRouteButton.doClick(); 497 } 498 createButton.setVisible(false); 499 _addFrame.setTitle(rbx.getString("LRouteEditTitle")); 500 } 501 502 /** 503 * Get the type letter from the possible LRoute conditional. 504 * 505 * @param logixSysName logix system name 506 * @param cSysName conditional system name 507 * @return the type letter 508 */ 509 char getRouteConditionalType(String logixSysName, String cSysName) { 510 if (cSysName.startsWith(logixSysName)) { 511 char[] chNum = cSysName.substring(logixSysName.length()).toCharArray(); 512 int i = 0; 513 while (Character.isDigit(chNum[i])) { 514 i++; 515 } 516 return chNum[i]; 517 } 518 return 0; 519 } 520 521 /** 522 * Extract the Control (input) and Action (output) elements and their 523 * states. 524 * 525 * @param cSysName the conditional system name 526 */ 527 void getControlsAndActions(String cSysName) { 528 Conditional c = _conditionalManager.getBySystemName(cSysName); 529 if (c != null) { 530 List<ConditionalAction> actionList = c.getCopyOfActions(); 531 boolean onChange = false; 532 for (int k = 0; k < actionList.size(); k++) { 533 ConditionalAction action = actionList.get(k); 534 int type; 535 switch (action.getType()) { 536 case SET_SENSOR: 537 type = SENSOR_TYPE; 538 break; 539 case SET_TURNOUT: 540 type = TURNOUT_TYPE; 541 break; 542 case SET_LIGHT: 543 type = LIGHT_TYPE; 544 break; 545 case SET_SIGNAL_APPEARANCE: 546 case SET_SIGNAL_HELD: 547 case CLEAR_SIGNAL_HELD: 548 case SET_SIGNAL_DARK: 549 case SET_SIGNAL_LIT: 550 type = SIGNAL_TYPE; 551 break; 552 case RUN_SCRIPT: 553 scriptFile.setText(action.getActionString()); 554 continue; 555 case PLAY_SOUND: 556 soundFile.setText(action.getActionString()); 557 continue; 558 default: 559 JOptionPane.showMessageDialog( 560 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarn"), 561 new Object[]{action.toString(), c.getSystemName()}), 562 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 563 continue; 564 } 565 String name = action.getDeviceName(); 566 String key = type + name; 567 RouteOutputElement elt = _outputUserMap.get(key); 568 if (elt == null) { // try in system name map 569 elt = _outputMap.get(key); 570 } 571 if (elt == null) { 572 JOptionPane.showMessageDialog( 573 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarn"), 574 new Object[]{action.toString(), c.getSystemName()}), 575 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 576 } else { 577 elt.setIncluded(true); 578 elt.setState(action.getActionData()); 579 boolean change = (action.getOption() == Conditional.ACTION_OPTION_ON_CHANGE); 580 if (k == 0) { 581 onChange = change; 582 } else if (change != onChange) { 583 JOptionPane.showMessageDialog( 584 _addFrame, java.text.MessageFormat.format(rbx.getString("OnChangeWarn"), 585 new Object[]{action.toString(), c.getSystemName()}), 586 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 587 } 588 } 589 } 590 List<ConditionalVariable> varList = c.getCopyOfStateVariables(); 591 for (int k = 0; k < varList.size(); k++) { 592 ConditionalVariable variable = varList.get(k); 593 Conditional.Type testState = variable.getType(); 594 //boolean negated = variable.isNegated(); 595 int type; 596 switch (testState) { 597 case SENSOR_ACTIVE: 598 type = SENSOR_TYPE; 599 //if (negated) testState = Conditional.TYPE_SENSOR_INACTIVE; 600 break; 601 case SENSOR_INACTIVE: 602 type = SENSOR_TYPE; 603 //if (negated) testState = Conditional.TYPE_SENSOR_ACTIVE; 604 break; 605 case TURNOUT_CLOSED: 606 type = TURNOUT_TYPE; 607 //if (negated) testState = Conditional.TYPE_TURNOUT_THROWN; 608 break; 609 case TURNOUT_THROWN: 610 type = TURNOUT_TYPE; 611 //if (negated) testState = Conditional.TYPE_TURNOUT_CLOSED; 612 break; 613 case LIGHT_ON: 614 type = LIGHT_TYPE; 615 //if (negated) testState = Conditional.TYPE_LIGHT_OFF; 616 break; 617 case LIGHT_OFF: 618 type = LIGHT_TYPE; 619 //if (negated) testState = Conditional.TYPE_LIGHT_ON; 620 break; 621 case SIGNAL_HEAD_LIT: 622 case SIGNAL_HEAD_RED: 623 case SIGNAL_HEAD_YELLOW: 624 case SIGNAL_HEAD_GREEN: 625 case SIGNAL_HEAD_DARK: 626 case SIGNAL_HEAD_FLASHRED: 627 case SIGNAL_HEAD_FLASHYELLOW: 628 case SIGNAL_HEAD_FLASHGREEN: 629 case SIGNAL_HEAD_HELD: 630 type = SIGNAL_TYPE; 631 break; 632 default: 633 if (!getLogixInitializer().equals(variable.getName())) { 634 JOptionPane.showMessageDialog( 635 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarnVar"), 636 new Object[]{variable.toString(), c.getSystemName()}), 637 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 638 } 639 continue; 640 } 641 int testStateInt = testState.getIntValue(); 642 Operator opern = variable.getOpern(); 643 if (k != 0 && (opern == Conditional.Operator.AND)) { 644 // guess this is a VETO 645 testStateInt += VETO; 646 } else if (onChange) { 647 testStateInt = Route.ONCHANGE; 648 } 649 String name = variable.getName(); 650 String key = type + name; 651 RouteInputElement elt = _inputUserMap.get(key); 652 if (elt == null) { // try in system name map 653 elt = _inputMap.get(key); 654 } 655 if (elt == null) { 656 if (!getLogixInitializer().equals(name)) { 657 JOptionPane.showMessageDialog( 658 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarnVar"), 659 new Object[]{variable.toString(), c.getSystemName()}), 660 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 661 } 662 } else { 663 elt.setIncluded(true); 664 elt.setState(testStateInt); 665 } 666 } 667 } 668 } // getControlsAndActions 669 670 /** 671 * Extract the Alignment Sensors and their types. 672 * 673 * @param cSysName the conditional system name 674 */ 675 void getAlignmentSensors(String cSysName) { 676 Conditional c = _conditionalManager.getBySystemName(cSysName); 677 if (c != null) { 678 AlignElement element = null; 679 List<ConditionalAction> actionList = c.getCopyOfActions(); 680 for (int k = 0; k < actionList.size(); k++) { 681 ConditionalAction action = actionList.get(k); 682 if (action.getType() != Conditional.Action.SET_SENSOR) { 683 JOptionPane.showMessageDialog( 684 _addFrame, java.text.MessageFormat.format(rbx.getString("AlignWarn1"), 685 new Object[]{action.toString(), c.getSystemName()}), 686 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 687 } else { 688 String name = action.getDeviceName(); 689 String key = SENSOR_TYPE + name; 690 element = _alignUserMap.get(key); 691 if (element == null) { // try in system name map 692 element = _alignMap.get(key); 693 } 694 if (element == null) { 695 JOptionPane.showMessageDialog( 696 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarn"), 697 new Object[]{action.toString(), c.getSystemName()}), 698 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 699 700 } else if (!name.equals(action.getDeviceName())) { 701 JOptionPane.showMessageDialog( 702 _addFrame, java.text.MessageFormat.format(rbx.getString("AlignWarn2"), 703 new Object[]{action.toString(), action.getDeviceName(), c.getSystemName()}), 704 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 705 706 } else { 707 element.setIncluded(true); 708 } 709 } 710 } 711 // the action elements are identified in getControlsAndActions(). 712 // Just identify the type of sensing 713 List<ConditionalVariable> varList = c.getCopyOfStateVariables(); 714 int atype = 0; 715 for (int k = 0; k < varList.size(); k++) { 716 ConditionalVariable variable = varList.get(k); 717 Conditional.Type testState = variable.getType(); 718 int type; 719 switch (testState) { 720 case SENSOR_ACTIVE: 721 case SENSOR_INACTIVE: 722 type = SENSOR_TYPE; 723 break; 724 case TURNOUT_CLOSED: 725 case TURNOUT_THROWN: 726 type = TURNOUT_TYPE; 727 break; 728 case LIGHT_ON: 729 case LIGHT_OFF: 730 type = LIGHT_TYPE; 731 break; 732 case SIGNAL_HEAD_LIT: 733 case SIGNAL_HEAD_RED: 734 case SIGNAL_HEAD_YELLOW: 735 case SIGNAL_HEAD_GREEN: 736 case SIGNAL_HEAD_DARK: 737 case SIGNAL_HEAD_FLASHRED: 738 case SIGNAL_HEAD_FLASHYELLOW: 739 case SIGNAL_HEAD_FLASHGREEN: 740 case SIGNAL_HEAD_HELD: 741 type = SIGNAL_TYPE; 742 break; 743 default: 744 if (!getLogixInitializer().equals(variable.getName())) { 745 JOptionPane.showMessageDialog( 746 _addFrame, java.text.MessageFormat.format(rbx.getString("TypeWarnVar"), 747 new Object[]{variable.toString(), c.getSystemName()}), 748 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 749 } 750 continue; 751 } 752 if (k == 0) { 753 atype = type; 754 } else if (atype != type) { 755 // more than one type. therefor, ALL 756 atype = ALL_TYPE; 757 break; 758 } 759 } 760 if (element != null) { 761 element.setState(atype); 762 } 763 } 764 } 765 766 /** 767 * Extract the Lock expression. For now, same as action control expression. 768 * 769 * @param cSysName the conditional system name 770 */ 771 void getLockConditions(String cSysName) { 772 Conditional c = _conditionalManager.getBySystemName(cSysName); 773 if (c != null) { 774 _lock = true; 775 // Verify conditional is what we think it is 776 ArrayList<RouteOutputElement> tList = makeTurnoutLockList(); 777 List<ConditionalAction> actionList = c.getCopyOfActions(); 778 if (actionList.size() != tList.size()) { 779 JOptionPane.showMessageDialog( 780 _addFrame, java.text.MessageFormat.format(rbx.getString("LockWarn1"), 781 new Object[]{Integer.toString(tList.size()), c.getSystemName(), 782 Integer.toString(actionList.size())}), 783 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 784 } 785 for (int k = 0; k < actionList.size(); k++) { 786 ConditionalAction action = actionList.get(k); 787 if (action.getType() != Conditional.Action.LOCK_TURNOUT) { 788 JOptionPane.showMessageDialog( 789 _addFrame, java.text.MessageFormat.format(rbx.getString("LockWarn2"), 790 new Object[]{action.getDeviceName(), c.getSystemName()}), 791 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 792 } else { 793 String name = action.getDeviceName(); 794 boolean found = false; 795 ArrayList<RouteOutputElement> lockList = makeTurnoutLockList(); 796 for (int j = 0; j < lockList.size(); j++) { 797 RouteOutputElement elt = lockList.get(j); 798 if (name.equals(elt.getUserName()) || name.equals(elt.getSysName())) { 799 found = true; 800 break; 801 } 802 } 803 if (!found) { 804 JOptionPane.showMessageDialog( 805 _addFrame, java.text.MessageFormat.format(rbx.getString("LockWarn3"), 806 new Object[]{name, c.getSystemName()}), 807 rbx.getString("EditDiff"), JOptionPane.WARNING_MESSAGE); 808 } 809 } 810 } 811 } 812 } 813 814 /** 815 * Responds to the Cancel button. 816 * 817 * @param e the action event 818 */ 819 void cancelPressed(ActionEvent e) { 820 if (_addFrame.getTitle().equals(rbx.getString("LRouteEditTitle"))) { // Warnings shown are useless when cancelling Add New LRoute 821 Logix logix = checkNamesOK(); 822 if (logix != null) { 823 logix.activateLogix(); 824 } 825 } 826 clearPage(); 827 } 828 829 @Override 830 protected void addPressed(ActionEvent e) { 831 makeEditWindow(); 832 _tabbedPane.setSelectedIndex(0); 833 createButton.setVisible(true); 834 cancelButton.setVisible(true); 835 _typePanel.setVisible(true); 836 _addFrame.setVisible(true); 837 _systemName.setEnabled(true); 838 _userName.setEnabled(true); 839 _addFrame.setTitle(rbx.getString("LRouteAddTitle")); 840 841 _addFrame.setEscapeKeyClosesWindow(true); 842 _addFrame.getRootPane().setDefaultButton(createButton); 843 } 844 845 /** 846 * Set up Create/Edit LRoute pane 847 */ 848 void makeEditWindow() { 849 buildLists(); 850 if (_addFrame == null) { 851 _addFrame = new JmriJFrame(rbx.getString("LRouteAddTitle"), false, false); 852 _addFrame.addHelpMenu("package.jmri.jmrit.beantable.LRouteAddEdit", true); 853 _addFrame.setLocation(100, 30); 854 855 _tabbedPane = new JTabbedPane(); 856 857 //////////////////////////////////// Tab 1 ///////////////////////////// 858 JPanel tab1 = new JPanel(); 859 tab1.setLayout(new BoxLayout(tab1, BoxLayout.Y_AXIS)); 860 tab1.add(Box.createVerticalStrut(10)); 861 // add system name 862 JPanel p = new JPanel(); 863 p.setLayout(new FlowLayout()); 864 p.add(new JLabel(Bundle.getMessage("LabelSystemName"))); 865 p.add(_systemName); 866 _systemName.setToolTipText(rbx.getString("SystemNameHint")); 867 tab1.add(p); 868 // add user name 869 p = new JPanel(); 870 p.setLayout(new FlowLayout()); 871 p.add(new JLabel(Bundle.getMessage("LabelUserName"))); 872 p.add(_userName); 873 _userName.setToolTipText(rbx.getString("UserNameHint")); 874 tab1.add(p); 875 876 JPanel pa = new JPanel(); 877 p = new JPanel(); 878 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); 879 p.add(new JLabel(rbx.getString("Guide1"))); 880 p.add(new JLabel(rbx.getString("Guide2"))); 881 p.add(new JLabel(rbx.getString("Guide3"))); 882 p.add(new JLabel(rbx.getString("Guide4"))); 883 pa.add(p); 884 tab1.add(pa); 885 886 _newRouteButton = new JRadioButton(rbx.getString("NewRoute"), true); 887 JRadioButton oldRoute = new JRadioButton(rbx.getString("OldRoute"), false); 888 _initializeButton = new JRadioButton(rbx.getString("Initialize"), false); 889 _newRouteButton.setToolTipText(rbx.getString("NewRouteHint")); 890 _newRouteButton.addActionListener((ActionEvent e) -> { 891 _newRouteType = true; 892 _systemName.setEnabled(true); 893 }); 894 oldRoute.setToolTipText(rbx.getString("OldRouteHint")); 895 oldRoute.addActionListener((ActionEvent e) -> { 896 _newRouteType = false; 897 _systemName.setEnabled(true); 898 }); 899 _initializeButton.setToolTipText(rbx.getString("InitializeHint")); 900 _initializeButton.addActionListener((ActionEvent e) -> { 901 _initialize = true; 902 _newRouteType = true; 903 _systemName.setEnabled(false); 904 _systemName.setText(getLogixInitializer()); 905 }); 906 _typePanel = makeShowButtons(_newRouteButton, oldRoute, _initializeButton, rbx.getString("LRouteType") + ":"); 907 _typePanel.setBorder(BorderFactory.createEtchedBorder()); 908 tab1.add(_typePanel); 909 tab1.add(Box.createVerticalGlue()); 910 911 // add buttons 912 JPanel pb = new JPanel(); 913 pb.setLayout(new FlowLayout()); 914 // Cancel button 915 pb.add(cancelButton); 916 cancelButton.addActionListener(this::cancelPressed); 917 cancelButton.setToolTipText(Bundle.getMessage("TooltipCancelRoute")); 918 cancelButton.setName("CancelButton"); 919 // Add Route button 920 pb.add(createButton); 921 createButton.addActionListener(this::createPressed); 922 createButton.setToolTipText(rbx.getString("CreateHint")); 923 createButton.setName("CreateButton"); 924 // Delete Route button 925 pb.add(deleteButton); 926 deleteButton.addActionListener(this::deletePressed); 927 deleteButton.setToolTipText(rbx.getString("DeleteHint")); 928 // Update Route button 929 pb.add(updateButton); 930 updateButton.addActionListener((ActionEvent e) -> { 931 updatePressed(); 932 }); 933 updateButton.setToolTipText(rbx.getString("UpdateHint")); 934 updateButton.setName("UpdateButton"); 935 936 // Show the initial buttons, and hide the others 937 cancelButton.setVisible(true); 938 updateButton.setVisible(false); 939 createButton.setVisible(false); 940 deleteButton.setVisible(false); 941 tab1.add(pb); 942 943 tab1.setVisible(true); 944 _tabbedPane.addTab(rbx.getString("BasicTab"), null, tab1, rbx.getString("BasicTabHint")); 945 946 //////////////////////////////////// Tab 2 ///////////////////////////// 947 JPanel tab2 = new JPanel(); 948 tab2.setLayout(new BoxLayout(tab2, BoxLayout.Y_AXIS)); 949 tab2.add(new JLabel(rbx.getString("OutputTitle") + ":")); 950 _outputAllButton = new JRadioButton(Bundle.getMessage("All"), true); 951 JRadioButton includedOutputButton = new JRadioButton(Bundle.getMessage("Included"), false); 952 tab2.add(makeShowButtons(_outputAllButton, includedOutputButton, null, Bundle.getMessage("Show") + ":")); 953 _outputAllButton.addActionListener((ActionEvent e) -> { 954 // Setup for display of all Turnouts, if needed 955 if (!_showAllOutput) { 956 _showAllOutput = true; 957 _outputModel.fireTableDataChanged(); 958 } 959 }); 960 includedOutputButton.addActionListener((ActionEvent e) -> { 961 // Setup for display of included Turnouts only, if needed 962 if (_showAllOutput) { 963 _showAllOutput = false; 964 initializeIncludedOutputList(); 965 _outputModel.fireTableDataChanged(); 966 } 967 }); 968 tab2.add(new JLabel(rbx.getString("PickOutput"))); 969 970 _outputModel = new RouteOutputModel(); 971 JTable routeOutputTable = new JTable(_outputModel); 972 _outputScrollPane = makeColumns(routeOutputTable, _setStateCombo, true); 973 tab2.add(_outputScrollPane, BorderLayout.CENTER); 974 tab2.setVisible(true); 975 _tabbedPane.addTab(rbx.getString("ActionTab"), null, tab2, rbx.getString("ActionTabHint")); 976 977 //////////////////////////////////// Tab 3 ///////////////////////////// 978 JPanel tab3 = new JPanel(); 979 tab3.setLayout(new BoxLayout(tab3, BoxLayout.Y_AXIS)); 980 tab3.add(new JLabel(rbx.getString("InputTitle") + ":")); 981 _inputAllButton = new JRadioButton(Bundle.getMessage("All"), true); 982 JRadioButton includedInputButton = new JRadioButton(Bundle.getMessage("Included"), false); 983 tab3.add(makeShowButtons(_inputAllButton, includedInputButton, null, Bundle.getMessage("Show") + ":")); 984 _inputAllButton.addActionListener((ActionEvent e) -> { 985 // Setup for display of all Turnouts, if needed 986 if (!_showAllInput) { 987 _showAllInput = true; 988 _inputModel.fireTableDataChanged(); 989 } 990 }); 991 includedInputButton.addActionListener((ActionEvent e) -> { 992 // Setup for display of included Turnouts only, if needed 993 if (_showAllInput) { 994 _showAllInput = false; 995 initializeIncludedInputList(); 996 _inputModel.fireTableDataChanged(); 997 } 998 }); 999 tab3.add(new JLabel(rbx.getString("PickInput"))); 1000 1001 _inputModel = new RouteInputModel(); 1002 JTable routeInputTable = new JTable(_inputModel); 1003 //ROW_HEIGHT = routeInputTable.getRowHeight(); 1004 _inputScrollPane = makeColumns(routeInputTable, _testStateCombo, true); 1005 tab3.add(_inputScrollPane, BorderLayout.CENTER); 1006 tab3.setVisible(true); 1007 _tabbedPane.addTab(rbx.getString("TriggerTab"), null, tab3, rbx.getString("TriggerTabHint")); 1008 1009 ////////////////////// Tab 4 ///////////////// 1010 JPanel tab4 = new JPanel(); 1011 tab4.setLayout(new BoxLayout(tab4, BoxLayout.Y_AXIS)); 1012 tab4.add(new JLabel(rbx.getString("MiscTitle") + ":")); 1013 // Enter filenames for sound, script 1014 JPanel p25 = new JPanel(); 1015 p25.setLayout(new FlowLayout()); 1016 p25.add(new JLabel(Bundle.getMessage("LabelPlaySound"))); 1017 JButton ss = new JButton("..."); 1018 ss.addActionListener((ActionEvent e) -> { 1019 setSoundPressed(); 1020 }); 1021 p25.add(ss); 1022 p25.add(soundFile); 1023 tab4.add(p25); 1024 1025 p25 = new JPanel(); 1026 p25.setLayout(new FlowLayout()); 1027 p25.add(new JLabel(Bundle.getMessage("LabelRunScript"))); 1028 ss = new JButton("..."); 1029 ss.addActionListener((ActionEvent e) -> { 1030 setScriptPressed(); 1031 }); 1032 p25.add(ss); 1033 p25.add(scriptFile); 1034 tab4.add(p25); 1035 1036 p25 = new JPanel(); 1037 p25.setLayout(new FlowLayout()); 1038 p25.add(new JLabel(rbx.getString("SetLocks") + ":")); 1039 _lockCheckBox = new JCheckBox(rbx.getString("Lock"), true); 1040 _lockCheckBox.addActionListener((ActionEvent e) -> { 1041 // Setup for display of all Turnouts, if needed 1042 _lock = _lockCheckBox.isSelected(); 1043 }); 1044 p25.add(_lockCheckBox); 1045 tab4.add(p25); 1046 1047 _alignAllButton = new JRadioButton(Bundle.getMessage("All"), true); 1048 JRadioButton includedAlignButton = new JRadioButton(Bundle.getMessage("Included"), false); 1049 tab4.add(makeShowButtons(_alignAllButton, includedAlignButton, null, Bundle.getMessage("Show") + ":")); 1050 _alignAllButton.addActionListener((ActionEvent e) -> { 1051 // Setup for display of all Turnouts, if needed 1052 if (!_showAllAlign) { 1053 _showAllAlign = true; 1054 _alignModel.fireTableDataChanged(); 1055 } 1056 }); 1057 includedAlignButton.addActionListener((ActionEvent e) -> { 1058 // Setup for display of included Turnouts only, if needed 1059 if (_showAllAlign) { 1060 _showAllAlign = false; 1061 initializeIncludedAlignList(); 1062 _alignModel.fireTableDataChanged(); 1063 } 1064 }); 1065 tab4.add(new JLabel(rbx.getString("PickAlign"))); 1066 _alignModel = new AlignmentModel(); 1067 JTable alignTable = new JTable(_alignModel); 1068 _alignCombo = new JComboBox<>(); 1069 for (String state : ALIGNMENT_STATES) { 1070 _alignCombo.addItem(state); 1071 } 1072 JScrollPane alignScrollPane = makeColumns(alignTable, _alignCombo, false); 1073 //alignTable.setPreferredScrollableViewportSize(new java.awt.Dimension(250,200)); 1074 _alignCombo = new JComboBox<>(); 1075 for (String state : ALIGNMENT_STATES) { 1076 _alignCombo.addItem(state); 1077 } 1078 tab4.add(alignScrollPane, BorderLayout.CENTER); 1079 tab4.setVisible(true); 1080 _tabbedPane.addTab(rbx.getString("MiscTab"), null, tab4, rbx.getString("MiscTabHint")); 1081 1082 Container contentPane = _addFrame.getContentPane(); 1083 //tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); 1084 1085 /////////////////////////////////// 1086 JPanel pt = new JPanel(); 1087 pt.add(_tabbedPane); 1088 contentPane.add(pt); 1089 1090 // set listener for window closing 1091 _addFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1092 @Override 1093 public void windowClosing(java.awt.event.WindowEvent e) { 1094 // remind to save, if Route was created or edited 1095 if (routeDirty) { 1096 showReminderMessage(); 1097 } 1098 clearPage(); 1099 _addFrame.setVisible(false); 1100 _inputModel.dispose(); 1101 _outputModel.dispose(); 1102 routeDirty = false; 1103 } 1104 }); 1105 1106 _addFrame.pack(); 1107 _inputAllButton.doClick(); 1108 _outputAllButton.doClick(); 1109 _alignAllButton.doClick(); 1110 _newRouteButton.doClick(); 1111 if (_initialize) { 1112 _initializeButton.doClick(); 1113 } 1114 } else { 1115 _addFrame.setVisible(true); 1116 } 1117 } 1118 1119 void showReminderMessage() { 1120 if (checkEnabled) return; 1121 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 1122 showInfoMessage(Bundle.getMessage("ReminderTitle"), Bundle.getMessage("ReminderSaveString", Bundle.getMessage("BeanNameLRoute")), 1123 getClassName(), 1124 "remindSaveRoute"); // NOI18N 1125 } 1126 1127 /* 1128 * Utility for addPressed 1129 */ 1130 JPanel makeShowButtons(JRadioButton allButton, JRadioButton includeButton, 1131 JRadioButton extraButton, String msg) { 1132 JPanel panel = new JPanel(); 1133 panel.add(new JLabel(msg)); 1134 panel.add(allButton); 1135 panel.add(includeButton); 1136 ButtonGroup selGroup = new ButtonGroup(); 1137 selGroup.add(allButton); 1138 selGroup.add(includeButton); 1139 if (extraButton != null) { 1140 panel.add(extraButton); 1141 selGroup.add(extraButton); 1142 } 1143 return panel; 1144 } 1145 1146 /* 1147 * Utility for addPressed 1148 */ 1149 JScrollPane makeColumns(JTable table, JComboBox<String> box, boolean specialBox) { 1150 table.setRowSelectionAllowed(false); 1151 //table.setPreferredScrollableViewportSize(new java.awt.Dimension(250,450)); 1152 TableColumnModel columnModel = table.getColumnModel(); 1153 1154 TableColumn sNameColumnT = columnModel.getColumn(RouteElementModel.SNAME_COLUMN); 1155 sNameColumnT.setResizable(true); 1156 sNameColumnT.setMinWidth(75); 1157 //sNameColumnT.setMaxWidth(110); 1158 1159 TableColumn uNameColumnT = columnModel.getColumn(RouteElementModel.UNAME_COLUMN); 1160 uNameColumnT.setResizable(true); 1161 uNameColumnT.setMinWidth(75); 1162 //uNameColumnT.setMaxWidth(260); 1163 1164 TableColumn typeColumnT = columnModel.getColumn(RouteElementModel.TYPE_COLUMN); 1165 typeColumnT.setResizable(true); 1166 typeColumnT.setMinWidth(50); 1167 //typeColumnT.setMaxWidth(110); 1168 1169 TableColumn includeColumnT = columnModel.getColumn(RouteElementModel.INCLUDE_COLUMN); 1170 includeColumnT.setResizable(false); 1171 includeColumnT.setMinWidth(30); 1172 includeColumnT.setMaxWidth(60); 1173 1174 TableColumn stateColumnT = columnModel.getColumn(RouteElementModel.STATE_COLUMN); 1175 if (specialBox) { 1176 box = new JComboBox<>(); 1177 stateColumnT.setCellEditor(new ComboBoxCellEditor(box)); 1178 } else { 1179 stateColumnT.setCellEditor(new DefaultCellEditor(box)); 1180 } 1181 stateColumnT.setResizable(false); 1182 stateColumnT.setMinWidth(75); 1183 //stateColumnT.setMaxWidth(1310); 1184 1185 return new JScrollPane(table); 1186 } 1187 1188 /** 1189 * Initialize list of included input elements 1190 */ 1191 void initializeIncludedInputList() { 1192 _includedInputList = new ArrayList<>(); 1193 for (int i = 0; i < _inputList.size(); i++) { 1194 if (_inputList.get(i).isIncluded()) { 1195 _includedInputList.add(_inputList.get(i)); 1196 } 1197 } 1198 } 1199 1200 /** 1201 * Initialize list of included input elements 1202 */ 1203 void initializeIncludedOutputList() { 1204 _includedOutputList = new ArrayList<>(); 1205 for (int i = 0; i < _outputList.size(); i++) { 1206 if (_outputList.get(i).isIncluded()) { 1207 _includedOutputList.add(_outputList.get(i)); 1208 } 1209 } 1210 } 1211 1212 /** 1213 * Initialize list of included alignment sensors 1214 */ 1215 void initializeIncludedAlignList() { 1216 _includedAlignList = new ArrayList<>(); 1217 for (int i = 0; i < _alignList.size(); i++) { 1218 if (_alignList.get(i).isIncluded()) { 1219 _includedAlignList.add(_alignList.get(i)); 1220 } 1221 } 1222 } 1223 1224 ArrayList<RouteOutputElement> makeTurnoutLockList() { 1225 ArrayList<RouteOutputElement> list = new ArrayList<>(); 1226 for (int i = 0; i < _outputList.size(); i++) { 1227 if (_outputList.get(i).isIncluded()) { 1228 RouteOutputElement elt = _outputList.get(i); 1229 if ((elt.getType() == TURNOUT_TYPE) && (elt.getState() != Route.TOGGLE)) { 1230 list.add(elt); 1231 } 1232 } 1233 } 1234 return list; 1235 } 1236 1237 void showMessage(String msg) { 1238 1239 JOptionPane.showMessageDialog( 1240 _addFrame, rbx.getString(msg), Bundle.getMessage("WarningTitle"), 1241 JOptionPane.WARNING_MESSAGE); 1242 } 1243 1244 boolean checkNewNamesOK() { 1245 // Get system name and user name 1246 String sName = _systemName.getText(); 1247 if (sName.length() == 0 || sName.equals(getLogixSystemPrefix())) { 1248 showMessage("EnterNames"); 1249 return false; 1250 } 1251 if (!sName.startsWith(getLogixSystemPrefix())) { 1252 sName = getLogixSystemPrefix() + sName; 1253 } 1254 // check if a Route with this system name already exists 1255 if (_logixManager.getBySystemName(sName) != null) { 1256 // Route already exists 1257 showMessage("DuplicateSys"); 1258 updateButton.setVisible(true); 1259 return false; 1260 } 1261 String uName = _userName.getText(); 1262 // check if a Route with the same user name exists 1263 if (!uName.isEmpty()) { 1264 if (_logixManager.getByUserName(uName) != null) { 1265 // Route with this user name already exists 1266 showMessage("DuplicateUser"); 1267 updateButton.setVisible(true); 1268 return false; 1269 } else { 1270 return true; 1271 } 1272 } 1273 _systemName.setText(sName); 1274 return true; 1275 } 1276 1277 Logix checkNamesOK() { 1278 // Get system name and user name 1279 String sName = _systemName.getText(); 1280 if (sName.length() == 0) { 1281 showMessage("EnterNames"); 1282 return null; 1283 } 1284 Logix logix = _logixManager.getBySystemName(sName); 1285 if (!sName.startsWith(getLogixSystemPrefix())) { 1286 sName = getLogixSystemPrefix() + sName; 1287 } 1288 if (logix != null) { 1289 return logix; 1290 } 1291 String uName = _userName.getText(); 1292 if (uName.length() != 0) { 1293 logix = _logixManager.getByUserName(uName); 1294 if (logix != null) { 1295 return logix; 1296 } 1297 } 1298 logix = _logixManager.createNewLogix(sName, uName); 1299 if (logix == null) { 1300 // should never get here 1301 log.error("Unknown failure to create Route with System Name: {}", sName); 1302 } 1303 return logix; 1304 } 1305 1306 JFileChooser soundChooser = null; 1307 1308 /** 1309 * Set the sound file 1310 */ 1311 void setSoundPressed() { 1312 if (soundChooser == null) { 1313 soundChooser = new jmri.util.swing.JmriJFileChooser(FileUtil.getUserFilesPath()); 1314 soundChooser.setFileFilter(new jmri.util.NoArchiveFileFilter()); 1315 } 1316 soundChooser.rescanCurrentDirectory(); 1317 int retVal = soundChooser.showOpenDialog(null); 1318 // handle selection or cancel 1319 if (retVal == JFileChooser.APPROVE_OPTION) { 1320 try { 1321 soundFile.setText(FileUtil.getPortableFilename(soundChooser.getSelectedFile().getCanonicalPath())); 1322 } catch (java.io.IOException e) { 1323 log.error("exception setting sound file", e); 1324 } 1325 } 1326 } 1327 1328 ScriptFileChooser scriptChooser = null; 1329 1330 /** 1331 * Set the script file 1332 */ 1333 void setScriptPressed() { 1334 if (scriptChooser == null) { 1335 scriptChooser = new ScriptFileChooser(); 1336 } 1337 scriptChooser.rescanCurrentDirectory(); 1338 int retVal = scriptChooser.showOpenDialog(null); 1339 // handle selection or cancel 1340 if (retVal == JFileChooser.APPROVE_OPTION) { 1341 try { 1342 scriptFile.setText(FileUtil.getPortableFilename(scriptChooser.getSelectedFile().getCanonicalPath())); 1343 } catch (java.io.IOException e) { 1344 log.error("exception setting script file", e); 1345 } 1346 } 1347 } 1348 1349 /** 1350 * Responds to the Add Route button. 1351 * 1352 * @param e the action event 1353 */ 1354 void createPressed(ActionEvent e) { 1355 if (!checkNewNamesOK()) { 1356 return; 1357 } 1358 updatePressed(); 1359 } 1360 1361 /** 1362 * Responds to the Delete button. 1363 * 1364 * @param e the action event 1365 */ 1366 void deletePressed(ActionEvent e) { 1367 Logix l = checkNamesOK(); 1368 if (l != null) { 1369 l.deActivateLogix(); 1370 // delete the Logix and all its Conditionals 1371 _logixManager.deleteLogix(l); 1372 } 1373 finishUpdate(); 1374 } 1375 1376 /** 1377 * Update the Route Table. 1378 */ 1379 void updatePressed() { 1380 Logix logix = checkNamesOK(); 1381 if (logix == null) { 1382 log.error("No Logix found!"); 1383 return; 1384 } 1385 String sName = logix.getSystemName(); 1386 // Check if the User Name has been changed 1387 String uName = _userName.getText(); 1388 logix.setUserName(uName); 1389 1390 initializeIncludedInputList(); 1391 initializeIncludedOutputList(); 1392 initializeIncludedAlignList(); 1393 if (log.isDebugEnabled()) { 1394 log.debug("updatePressed: _includedInputList.size()= {}, _includedOutputList.size()= {}, _includedAlignList.size()= {}", _includedInputList.size(), _includedOutputList.size(), _includedAlignList.size()); 1395 } 1396 ////// Construct output actions for trigger conditionals /////////// 1397 ArrayList<ConditionalAction> actionList = new ArrayList<>(); 1398 for (int i = 0; i < _includedOutputList.size(); i++) { 1399 RouteOutputElement elt = _includedOutputList.get(i); 1400 String name = elt.getUserName(); 1401 if (name == null || name.length() == 0) { 1402 name = elt.getSysName(); 1403 } 1404 int state = elt.getState(); // actionData 1405 Conditional.Action actionType = Conditional.Action.NONE; 1406 String params = ""; 1407 switch (elt.getType()) { 1408 case SENSOR_TYPE: 1409 actionType = Conditional.Action.SET_SENSOR; 1410 break; 1411 case TURNOUT_TYPE: 1412 actionType = Conditional.Action.SET_TURNOUT; 1413 break; 1414 case LIGHT_TYPE: 1415 actionType = Conditional.Action.SET_LIGHT; 1416 break; 1417 case SIGNAL_TYPE: 1418 actionType = Conditional.Action.SET_SIGNAL_APPEARANCE; 1419 if (state > OFFSET) { 1420 actionType = Conditional.Action.getOperatorFromIntValue(state & ~OFFSET); 1421 } 1422 break; 1423 default: 1424 log.debug("updatePressed: Unknown action type {}", elt.getType()); 1425 } 1426 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1427 actionType, name, state, params)); 1428 } 1429 String file = scriptFile.getText(); 1430 if (file.length() > 0) { 1431 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1432 Conditional.Action.RUN_SCRIPT, "", -1, file)); 1433 } 1434 file = soundFile.getText(); 1435 if (file.length() > 0) { 1436 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1437 Conditional.Action.PLAY_SOUND, "", -1, file)); 1438 } 1439 ArrayList<ConditionalAction> onChangeList = cloneActionList(actionList, Conditional.ACTION_OPTION_ON_CHANGE); 1440 1441 /////// Construct 'AND' clause from 'VETO' controls //////// 1442 ArrayList<ConditionalVariable> vetoList = new ArrayList<>(); 1443 if (!_initialize) { 1444 for (int i = 0; i < _includedInputList.size(); i++) { 1445 RouteInputElement elt = _includedInputList.get(i); 1446 String name = elt.getUserName(); 1447 if (name == null || name.length() == 0) { 1448 name = elt.getSysName(); 1449 } 1450 //int opern = newRouteType ? Conditional.OPERATOR_AND : Conditional.OPERATOR_OR; 1451 Operator opern = Conditional.Operator.AND; 1452 if (i == 0) { 1453 opern = Conditional.Operator.NONE; 1454 } 1455 int state = elt.getState(); 1456 if (VETO < state) { 1457 vetoList.add(new ConditionalVariable(true, opern, 1458 Conditional.Type.getOperatorFromIntValue(state & ~VETO), name, _newRouteType)); 1459 } 1460 } 1461 } 1462 1463 ///////////////// Make Trigger Conditional Controls ///////////////// 1464 ArrayList<ConditionalVariable> oneTriggerList = new ArrayList<>(); 1465 ArrayList<ConditionalVariable> twoTriggerList = new ArrayList<>(); 1466 if (!_initialize) { 1467 for (int i = 0; i < _includedInputList.size(); i++) { 1468 RouteInputElement elt = _includedInputList.get(i); 1469 String name = elt.getUserName(); 1470 if (name == null || name.length() == 0) { 1471 name = elt.getSysName(); 1472 } 1473 Operator opern = _newRouteType ? Conditional.Operator.OR : Conditional.Operator.AND; 1474 if (i == 0) { 1475 opern = Conditional.Operator.NONE; 1476 } 1477 int type = elt.getState(); 1478 if (VETO > type) { 1479 if (Route.ONCHANGE == type) { 1480 switch (elt.getType()) { 1481 case SENSOR_TYPE: 1482 type = Conditional.TYPE_SENSOR_ACTIVE; 1483 break; 1484 case TURNOUT_TYPE: 1485 type = Conditional.TYPE_TURNOUT_CLOSED; 1486 break; 1487 case LIGHT_TYPE: 1488 type = Conditional.TYPE_LIGHT_ON; 1489 break; 1490 case SIGNAL_TYPE: 1491 type = Conditional.TYPE_SIGNAL_HEAD_LIT; 1492 break; 1493 default: 1494 log.debug("updatePressed: Unknown state variable type {}", elt.getType()); 1495 } 1496 twoTriggerList.add(new ConditionalVariable(false, opern, Conditional.Type.getOperatorFromIntValue(type), name, true)); 1497 } else { 1498 oneTriggerList.add(new ConditionalVariable(false, opern, Conditional.Type.getOperatorFromIntValue(type), name, true)); 1499 } 1500 } 1501 } 1502 if (actionList.isEmpty()) { 1503 JOptionPane.showMessageDialog( 1504 _addFrame, rbx.getString("noAction"), 1505 rbx.getString("addErr"), JOptionPane.ERROR_MESSAGE); 1506 return; 1507 } 1508 } else { 1509 oneTriggerList.add(new ConditionalVariable(false, Conditional.Operator.NONE, 1510 Conditional.Type.NONE, getLogixInitializer(), true)); 1511 } 1512 if (log.isDebugEnabled()) { 1513 log.debug("actionList.size()= {}, oneTriggerList.size()= {}, twoTriggerList.size()= {}, onChangeList.size()= {}, vetoList.size()= {}", actionList.size(), oneTriggerList.size(), twoTriggerList.size(), onChangeList.size(), vetoList.size()); 1514 } 1515 logix.deActivateLogix(); 1516 1517 // remove old Conditionals for actions (ver 2.5.2 only -remove a bad idea) 1518 char[] ch = sName.toCharArray(); 1519 int hash = 0; 1520 for (int i = 0; i < ch.length; i++) { 1521 hash += ch[i]; 1522 } 1523 String cSystemName = getConditionalSystemPrefix() + "T" + hash; 1524 removeConditionals(cSystemName, logix); 1525 cSystemName = getConditionalSystemPrefix() + "F" + hash; 1526 removeConditionals(cSystemName, logix); 1527 cSystemName = getConditionalSystemPrefix() + "A" + hash; 1528 removeConditionals(cSystemName, logix); 1529 cSystemName = getConditionalSystemPrefix() + "L" + hash; 1530 removeConditionals(cSystemName, logix); 1531 int n = 0; 1532 do { 1533 n++; 1534 cSystemName = sName + n + "A"; 1535 } while (removeConditionals(cSystemName, logix)); 1536 n = 0; 1537 do { 1538 n++; 1539 cSystemName = sName + n + "T"; 1540 } while (removeConditionals(cSystemName, logix)); 1541 cSystemName = sName + "L"; 1542 removeConditionals(cSystemName, logix); 1543 1544 //String cUserName = null; 1545 int numConds = 1; 1546 if (_newRouteType) { 1547 numConds = makeRouteConditional(numConds, /*false,*/ actionList, oneTriggerList, 1548 vetoList, logix, sName, uName, "T"); 1549 if (!_initialize && twoTriggerList.size() > 0) { 1550 numConds = makeRouteConditional(numConds, /*true, actionList,*/ onChangeList, twoTriggerList, 1551 null, logix, sName, uName, "T"); 1552 } 1553 } else { 1554 for (int i = 0; i < oneTriggerList.size(); i++) { 1555 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1556 vList.add(oneTriggerList.get(i)); 1557 numConds = makeRouteConditional(numConds, /*false,*/ actionList, vList, 1558 vetoList, logix, sName, uName, "T"); 1559 } 1560 for (int i = 0; i < twoTriggerList.size(); i++) { 1561 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1562 vList.add(twoTriggerList.get(i)); 1563 numConds = makeRouteConditional(numConds, /*true, actionList,*/ onChangeList, vList, 1564 vetoList, logix, sName, uName, "T"); 1565 } 1566 } 1567 if (numConds == 1) { 1568 JOptionPane.showMessageDialog( 1569 _addFrame, rbx.getString("noVars"), 1570 rbx.getString("addErr"), JOptionPane.ERROR_MESSAGE); 1571 return; 1572 } 1573 1574 ///////////////// Make Alignment Conditionals ////////////////////////// 1575 numConds = 1; 1576 for (int i = 0; i < _includedAlignList.size(); i++) { 1577 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1578 ArrayList<ConditionalAction> aList = new ArrayList<>(); 1579 AlignElement sensor = _includedAlignList.get(i); 1580 String name = sensor.getUserName(); 1581 if (name == null || name.length() == 0) { 1582 name = sensor.getSysName(); 1583 } 1584 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1585 Conditional.Action.SET_SENSOR, name, Sensor.ACTIVE, "")); 1586 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE, 1587 Conditional.Action.SET_SENSOR, name, Sensor.INACTIVE, "")); 1588 int alignType = sensor.getState(); 1589 for (int k = 0; k < _includedOutputList.size(); k++) { 1590 RouteOutputElement elt = _includedOutputList.get(k); 1591 Conditional.Type varType = Conditional.Type.NONE; 1592 boolean add = (ALL_TYPE == alignType); 1593 switch (elt.getType()) { 1594 case SENSOR_TYPE: 1595 if (alignType == SENSOR_TYPE) { 1596 add = true; 1597 } 1598 switch (elt.getState()) { 1599 case Sensor.INACTIVE: 1600 varType = Conditional.Type.SENSOR_INACTIVE; 1601 break; 1602 case Sensor.ACTIVE: 1603 varType = Conditional.Type.SENSOR_ACTIVE; 1604 break; 1605 case Route.TOGGLE: 1606 add = false; 1607 break; 1608 default: 1609 log.warn("Unexpected state {} from elt.getState() in SENSOR_TYPE", elt.getState()); 1610 break; 1611 } 1612 break; 1613 case TURNOUT_TYPE: 1614 if (alignType == TURNOUT_TYPE) { 1615 add = true; 1616 } 1617 switch (elt.getState()) { 1618 case Turnout.CLOSED: 1619 varType = Conditional.Type.TURNOUT_CLOSED; 1620 break; 1621 case Turnout.THROWN: 1622 varType = Conditional.Type.TURNOUT_THROWN; 1623 break; 1624 case Route.TOGGLE: 1625 add = false; 1626 break; 1627 default: 1628 log.warn("Unexpected state {} from elt.getState() in TURNOUT_TYPE", elt.getState()); 1629 break; 1630 } 1631 break; 1632 case LIGHT_TYPE: 1633 if (alignType == LIGHT_TYPE) { 1634 add = true; 1635 } 1636 switch (elt.getState()) { 1637 case Light.ON: 1638 varType = Conditional.Type.LIGHT_ON; 1639 break; 1640 case Light.OFF: 1641 varType = Conditional.Type.LIGHT_OFF; 1642 break; 1643 case Route.TOGGLE: 1644 add = false; 1645 break; 1646 default: 1647 log.warn("Unexpected state {} from elt.getState() in LIGHT_TYPE", elt.getState()); 1648 break; 1649 } 1650 break; 1651 case SIGNAL_TYPE: 1652 if (alignType == SIGNAL_TYPE) { 1653 add = true; 1654 } 1655 switch (elt.getState()) { 1656 case SET_SIGNAL_DARK: 1657 case SignalHead.DARK: 1658 varType = Conditional.Type.SIGNAL_HEAD_DARK; 1659 break; 1660 case SignalHead.RED: 1661 varType = Conditional.Type.SIGNAL_HEAD_RED; 1662 break; 1663 case SignalHead.FLASHRED: 1664 varType = Conditional.Type.SIGNAL_HEAD_FLASHRED; 1665 break; 1666 case SignalHead.YELLOW: 1667 varType = Conditional.Type.SIGNAL_HEAD_YELLOW; 1668 break; 1669 case SignalHead.FLASHYELLOW: 1670 varType = Conditional.Type.SIGNAL_HEAD_FLASHYELLOW; 1671 break; 1672 case SignalHead.GREEN: 1673 varType = Conditional.Type.SIGNAL_HEAD_GREEN; 1674 break; 1675 case SignalHead.FLASHGREEN: 1676 varType = Conditional.Type.SIGNAL_HEAD_FLASHGREEN; 1677 break; 1678 case SET_SIGNAL_HELD: 1679 varType = Conditional.Type.SIGNAL_HEAD_HELD; 1680 break; 1681 case CLEAR_SIGNAL_HELD: 1682 add = false; // don't know how to test for this 1683 break; 1684 case SET_SIGNAL_LIT: 1685 varType = Conditional.Type.SIGNAL_HEAD_LIT; 1686 break; 1687 default: 1688 log.warn("Unexpected state {} from elt.getState() in SIGNAL_TYPE", elt.getState()); 1689 break; 1690 } 1691 break; 1692 default: 1693 log.debug("updatePressed: Unknown Alignment state variable type {}", elt.getType()); 1694 } 1695 if (add && !_initialize) { 1696 String eltName = elt.getUserName(); 1697 if (eltName == null || eltName.length() == 0) { 1698 eltName = elt.getSysName(); 1699 } 1700 vList.add(new ConditionalVariable(false, Conditional.Operator.AND, 1701 varType, eltName, true)); 1702 } 1703 } 1704 if (vList.size() > 0) { 1705 numConds = makeAlignConditional(numConds, aList, vList, logix, sName, uName); 1706 } else { 1707 JOptionPane.showMessageDialog( 1708 _addFrame, java.text.MessageFormat.format(rbx.getString("NoAlign"), 1709 new Object[]{name, sensor.getAlignType()}), 1710 Bundle.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE); 1711 } 1712 } 1713 ///////////////// Make Lock Conditional ////////////////////////// 1714 if (_lock) { 1715 ArrayList<ConditionalAction> aList = new ArrayList<>(); 1716 for (int k = 0; k < _includedOutputList.size(); k++) { 1717 RouteOutputElement elt = _includedOutputList.get(k); 1718 if (elt.getType() != TURNOUT_TYPE) { 1719 continue; 1720 } 1721 if (elt.getState() == Route.TOGGLE) { 1722 continue; 1723 } 1724 String eltName = elt.getUserName(); 1725 if (eltName == null || eltName.length() == 0) { 1726 eltName = elt.getSysName(); 1727 } 1728 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1729 Conditional.Action.LOCK_TURNOUT, 1730 eltName, Turnout.LOCKED, "")); 1731 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE, 1732 Conditional.Action.LOCK_TURNOUT, 1733 eltName, Turnout.UNLOCKED, "")); 1734 } 1735 makeRouteConditional(numConds, /*false,*/ aList, oneTriggerList, 1736 vetoList, logix, sName, uName, "L"); 1737 } 1738 log.debug("Conditionals added= {}", logix.getNumConditionals()); 1739 for (int i = 0; i < logix.getNumConditionals(); i++) { 1740 log.debug("Conditional SysName= \"{}\"", logix.getConditionalByNumberOrder(i)); 1741 } 1742 logix.activateLogix(); 1743 log.debug("Conditionals added= {}", logix.getNumConditionals()); 1744 for (int i = 0; i < logix.getNumConditionals(); i++) { 1745 log.debug("Conditional SysName= \"{}\"", logix.getConditionalByNumberOrder(i)); 1746 } 1747 finishUpdate(); 1748 } //updatePressed 1749 1750 boolean removeConditionals(String cSystemName, Logix logix) { 1751 Conditional c = _conditionalManager.getBySystemName(cSystemName); 1752 if (c != null) { 1753 logix.deleteConditional(cSystemName); 1754 return true; 1755 } 1756 return false; 1757 } 1758 1759 /** 1760 * Create a new Route conditional. 1761 * 1762 * @param numConds number of existing route conditionals 1763 * @param actionList actions to take in conditional 1764 * @param triggerList triggers for conditional to take actions 1765 * @param vetoList controls that veto taking actions 1766 * @param logix Logix to add the conditional to 1767 * @param sName system name for conditional 1768 * @param uName user name for conditional 1769 * @param type type of conditional 1770 * @return number of conditionals after the creation 1771 * @throws IllegalArgumentException if "user input no good" 1772 */ 1773 int makeRouteConditional(int numConds, /*boolean onChange,*/ ArrayList<ConditionalAction> actionList, 1774 ArrayList<ConditionalVariable> triggerList, ArrayList<ConditionalVariable> vetoList, 1775 Logix logix, String sName, String uName, String type) { 1776 if (log.isDebugEnabled()) { 1777 log.debug("makeRouteConditional: numConds= {}, triggerList.size()= {}", numConds, triggerList.size()); 1778 } 1779 if (triggerList.isEmpty() && (vetoList == null || vetoList.isEmpty())) { 1780 return numConds; 1781 } 1782 StringBuilder antecedent = new StringBuilder(); 1783 ArrayList<ConditionalVariable> varList = new ArrayList<>(); 1784 1785 int tSize = triggerList.size(); 1786 if (tSize > 0) { 1787 if (tSize > 1) { 1788 antecedent.append("("); 1789 } 1790 antecedent.append("R1"); // NOI18N 1791 for (int i = 1; i < tSize; i++) { 1792 antecedent.append(" ").append(Bundle.getMessage("LogicOR")).append(" R").append(i + 1); // NOI18N 1793 } 1794 if (tSize > 1) { 1795 antecedent.append(")"); 1796 } 1797 for (int i = 0; i < triggerList.size(); i++) { 1798 //varList.add(cloneVariable(triggerList.get(i))); 1799 varList.add(triggerList.get(i)); 1800 } 1801 } else { 1802 } 1803 if (vetoList != null && vetoList.size() > 0) { 1804 int vSize = vetoList.size(); 1805 if (tSize > 0) { 1806 antecedent.append(" ").append(Bundle.getMessage("LogicAND")).append(" "); 1807 } 1808 if (vSize > 1) { 1809 antecedent.append("("); 1810 } 1811 antecedent.append(Bundle.getMessage("LogicNOT")).append(" R").append(1 + tSize); // NOI18N 1812 for (int i = 1; i < vSize; i++) { 1813 antecedent.append(" ").append(Bundle.getMessage("LogicAND")).append(" ").append(Bundle.getMessage("LogicNOT")).append(" R").append(i + 1 + tSize); // NOI18N 1814 } 1815 if (vSize > 1) { 1816 antecedent.append(")"); 1817 } 1818 for (int i = 0; i < vetoList.size(); i++) { 1819 //varList.add(cloneVariable(vetoList.get(i))); 1820 varList.add(vetoList.get(i)); 1821 } 1822 } 1823 String cSystemName = sName + numConds + type; 1824 String cUserName = CONDITIONAL_USER_PREFIX + numConds + "C " + uName; 1825 Conditional c = null; 1826 try { 1827 c = _conditionalManager.createNewConditional(cSystemName, cUserName); 1828 } catch (Exception ex) { 1829 // user input no good 1830 handleCreateException(sName); 1831 // throw without creating any 1832 throw new IllegalArgumentException("user input no good"); 1833 } 1834 c.setStateVariables(varList); 1835 //int option = onChange ? Conditional.ACTION_OPTION_ON_CHANGE : Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE; 1836 //c.setAction(cloneActionList(actionList, option)); 1837 c.setAction(actionList); 1838 Conditional.AntecedentOperator logicType = 1839 _newRouteType 1840 ? Conditional.AntecedentOperator.MIXED 1841 : Conditional.AntecedentOperator.ALL_AND; 1842 c.setLogicType(logicType, antecedent.toString()); 1843 logix.addConditional(cSystemName, 0); 1844 log.debug("Conditional added: SysName= \"{}\"", cSystemName); 1845 c.calculate(true, null); 1846 numConds++; 1847 1848 return numConds; 1849 } 1850 1851 void handleCreateException(String sysName) { 1852 JOptionPane.showMessageDialog(_addFrame, 1853 Bundle.getMessage("ErrorLRouteAddFailed", sysName) + "\n" + Bundle.getMessage("ErrorAddFailedCheck"), 1854 Bundle.getMessage("ErrorTitle"), 1855 JOptionPane.ERROR_MESSAGE); 1856 } 1857 1858 /** 1859 * Create a new alignment conditional. 1860 * 1861 * @param numConds number of existing route conditionals 1862 * @param actionList actions to take in conditional 1863 * @param triggerList triggers for conditional to take actions 1864 * @param logix Logix to add the conditional to 1865 * @param sName system name for conditional 1866 * @param uName user name for conditional 1867 * @return number of conditionals after the creation 1868 * @throws IllegalArgumentException if "user input no good" 1869 */ 1870 int makeAlignConditional(int numConds, ArrayList<ConditionalAction> actionList, 1871 ArrayList<ConditionalVariable> triggerList, 1872 Logix logix, String sName, String uName) { 1873 if (triggerList.isEmpty()) { 1874 return numConds; 1875 } 1876 String cSystemName = sName + numConds + "A"; 1877 String cUserName = CONDITIONAL_USER_PREFIX + numConds + "A " + uName; 1878 Conditional c = null; 1879 try { 1880 c = _conditionalManager.createNewConditional(cSystemName, cUserName); 1881 } catch (Exception ex) { 1882 // user input no good 1883 handleCreateException(sName); 1884 // throw without creating any 1885 throw new IllegalArgumentException("user input no good"); 1886 } 1887 c.setStateVariables(triggerList); 1888 //c.setAction(cloneActionList(actionList, Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE)); 1889 c.setAction(actionList); 1890 c.setLogicType(Conditional.AntecedentOperator.ALL_AND, ""); 1891 logix.addConditional(cSystemName, 0); 1892 log.debug("Conditional added: SysName= \"{}\"", cSystemName); 1893 c.calculate(true, null); 1894 numConds++; 1895 return numConds; 1896 } 1897 1898 ArrayList<ConditionalAction> cloneActionList(ArrayList<ConditionalAction> actionList, int option) { 1899 ArrayList<ConditionalAction> list = new ArrayList<>(); 1900 for (int i = 0; i < actionList.size(); i++) { 1901 ConditionalAction action = actionList.get(i); 1902 ConditionalAction clone = new DefaultConditionalAction(); 1903 clone.setType(action.getType()); 1904 clone.setOption(option); 1905 clone.setDeviceName(action.getDeviceName()); 1906 clone.setActionData(action.getActionData()); 1907 clone.setActionString(action.getActionString()); 1908 list.add(clone); 1909 } 1910 return list; 1911 } 1912 1913 void finishUpdate() { 1914 routeDirty = true; 1915 clearPage(); 1916 } 1917 1918 void clearPage() { 1919 // move to show all turnouts if not there 1920 cancelIncludedOnly(); 1921 deleteButton.setVisible(false); 1922 cancelButton.setVisible(false); 1923 updateButton.setVisible(false); 1924 createButton.setVisible(false); 1925 _systemName.setText(""); 1926 _userName.setText(""); 1927 soundFile.setText(""); 1928 scriptFile.setText(""); 1929 for (int i = _inputList.size() - 1; i >= 0; i--) { 1930 _inputList.get(i).setIncluded(false); 1931 } 1932 for (int i = _outputList.size() - 1; i >= 0; i--) { 1933 _outputList.get(i).setIncluded(false); 1934 } 1935 for (int i = _alignList.size() - 1; i >= 0; i--) { 1936 _alignList.get(i).setIncluded(false); 1937 } 1938 _lock = false; 1939 _newRouteType = true; 1940 _newRouteButton.doClick(); 1941 _lockCheckBox.setSelected(_lock); 1942 if (routeDirty) { 1943 showReminderMessage(); 1944 routeDirty = false; 1945 } 1946 _addFrame.setVisible(false); 1947 } 1948 1949 /** 1950 * Cancels included only option 1951 */ 1952 void cancelIncludedOnly() { 1953 if (!_showAllInput) { 1954 _inputAllButton.doClick(); 1955 } 1956 if (!_showAllOutput) { 1957 _outputAllButton.doClick(); 1958 } 1959 if (!_showAllAlign) { 1960 _alignAllButton.doClick(); 1961 } 1962 } 1963 1964 private String[] getInputComboBoxItems(int type) { 1965 switch (type) { 1966 case SENSOR_TYPE: 1967 return INPUT_SENSOR_STATES; 1968 case TURNOUT_TYPE: 1969 return INPUT_TURNOUT_STATES; 1970 case LIGHT_TYPE: 1971 return INPUT_LIGHT_STATES; 1972 case SIGNAL_TYPE: 1973 return INPUT_SIGNAL_STATES; 1974 default: 1975 log.warn("Unhandled object type: {}", type); 1976 break; 1977 } 1978 return new String[]{}; 1979 } 1980 1981 private String[] getOutputComboBoxItems(int type) { 1982 switch (type) { 1983 case SENSOR_TYPE: 1984 return OUTPUT_SENSOR_STATES; 1985 case TURNOUT_TYPE: 1986 return OUTPUT_TURNOUT_STATES; 1987 case LIGHT_TYPE: 1988 return OUTPUT_LIGHT_STATES; 1989 case SIGNAL_TYPE: 1990 return OUTPUT_SIGNAL_STATES; 1991 default: 1992 log.warn("Unhandled type: {}", type); 1993 } 1994 return new String[]{}; 1995 } 1996 1997////////////////////////////// Internal Utility Classes //////////////////////////////// 1998 public class ComboBoxCellEditor extends DefaultCellEditor { 1999 2000 ComboBoxCellEditor() { 2001 super(new JComboBox<String>()); 2002 } 2003 2004 ComboBoxCellEditor(JComboBox<String> comboBox) { 2005 super(comboBox); 2006 } 2007 2008 @SuppressWarnings("unchecked") // getComponent call requires an unchecked cast 2009 @Override 2010 public Component getTableCellEditorComponent(JTable table, Object value, 2011 boolean isSelected, int row, int column) { 2012 //RouteElementModel model = (RouteElementModel)((jmri.util.com.sun.TableSorter)table.getModel()).getTableModel(); 2013 RouteElementModel model = (RouteElementModel) table.getModel(); 2014 //ArrayList <RouteElement> elementList = null; 2015 //int type = 0; 2016 RouteElement elt; 2017 String[] items; 2018 if (model.isInput()) { 2019 if (_showAllInput) { 2020 elt = _inputList.get(row); 2021 } else { 2022 elt = _includedInputList.get(row); 2023 } 2024 items = getInputComboBoxItems(elt.getType()); 2025 } else { 2026 if (_showAllOutput) { 2027 elt = _outputList.get(row); 2028 } else { 2029 elt = _includedOutputList.get(row); 2030 } 2031 items = getOutputComboBoxItems(elt.getType()); 2032 } 2033 JComboBox<String> comboBox = (JComboBox<String>) getComponent(); 2034 comboBox.removeAllItems(); 2035 for (String item : items) { 2036 comboBox.addItem(item); 2037 } 2038 return super.getTableCellEditorComponent(table, value, isSelected, row, column); 2039 } 2040 } 2041 2042 /** 2043 * Base Table model for selecting Route elements 2044 */ 2045 public abstract class RouteElementModel extends AbstractTableModel implements PropertyChangeListener { 2046 2047 abstract public boolean isInput(); 2048 2049 @Override 2050 public Class<?> getColumnClass(int c) { 2051 if (c == INCLUDE_COLUMN) { 2052 return Boolean.class; 2053 } else { 2054 return String.class; 2055 } 2056 } 2057 2058 @Override 2059 public int getColumnCount() { 2060 return 5; 2061 } 2062 2063 @Override 2064 public String getColumnName(int c) { 2065 switch (c) { 2066 case SNAME_COLUMN: 2067 return Bundle.getMessage("ColumnSystemName"); 2068 case UNAME_COLUMN: 2069 return Bundle.getMessage("ColumnUserName"); 2070 case TYPE_COLUMN: 2071 return rbx.getString("Type"); 2072 case INCLUDE_COLUMN: 2073 return Bundle.getMessage("Include"); 2074 default: 2075 log.warn("Unhandled column type: {}", c); 2076 break; 2077 } 2078 return ""; 2079 } 2080 2081 @Override 2082 public boolean isCellEditable(int r, int c) { 2083 return ((c == INCLUDE_COLUMN) || (c == STATE_COLUMN)); 2084 } 2085 2086 @Override 2087 public void propertyChange(java.beans.PropertyChangeEvent e) { 2088 if (e.getPropertyName().equals("length")) { 2089 // a new NamedBean is available in the manager 2090 fireTableDataChanged(); 2091 } 2092 } 2093 2094 public void dispose() { 2095 InstanceManager.turnoutManagerInstance().removePropertyChangeListener(this); 2096 } 2097 2098 public static final int SNAME_COLUMN = 0; 2099 public static final int UNAME_COLUMN = 1; 2100 public static final int TYPE_COLUMN = 2; 2101 public static final int INCLUDE_COLUMN = 3; 2102 public static final int STATE_COLUMN = 4; 2103 } 2104 2105 /** 2106 * Table model for selecting input variables 2107 */ 2108 class RouteInputModel extends RouteElementModel { 2109 2110 @Override 2111 public boolean isInput() { 2112 return true; 2113 } 2114 2115 @Override 2116 public String getColumnName(int c) { 2117 if (c == STATE_COLUMN) { 2118 return rbx.getString("SetTrigger"); 2119 } 2120 return super.getColumnName(c); 2121 } 2122 2123 @Override 2124 public int getRowCount() { 2125 if (_showAllInput) { 2126 return _inputList.size(); 2127 } else { 2128 return _includedInputList.size(); 2129 } 2130 } 2131 2132 @Override 2133 public Object getValueAt(int r, int c) { 2134 ArrayList<RouteInputElement> inputList; 2135 if (_showAllInput) { 2136 inputList = _inputList; 2137 } else { 2138 inputList = _includedInputList; 2139 } 2140 // some error checking 2141 if (r >= inputList.size()) { 2142 log.debug("row out of range"); 2143 return null; 2144 } 2145 switch (c) { 2146 case SNAME_COLUMN: 2147 return inputList.get(r).getSysName(); 2148 case UNAME_COLUMN: 2149 return inputList.get(r).getUserName(); 2150 case TYPE_COLUMN: 2151 return inputList.get(r).getTypeString(); 2152 case INCLUDE_COLUMN: 2153 return inputList.get(r).isIncluded(); 2154 case STATE_COLUMN: 2155 return inputList.get(r).getTestState(); 2156 default: 2157 return null; 2158 } 2159 } 2160 2161 @Override 2162 public void setValueAt(Object type, int r, int c) { 2163 ArrayList<RouteInputElement> inputList; 2164 if (_showAllInput) { 2165 inputList = _inputList; 2166 } else { 2167 inputList = _includedInputList; 2168 } 2169 switch (c) { 2170 case INCLUDE_COLUMN: 2171 inputList.get(r).setIncluded(((Boolean) type)); 2172 break; 2173 case STATE_COLUMN: 2174 inputList.get(r).setTestState((String) type); 2175 break; 2176 default: 2177 log.warn("Unexpected column {} in setValueAt", c); 2178 break; 2179 } 2180 } 2181 } 2182 2183 /** 2184 * Table model for selecting output variables 2185 */ 2186 class RouteOutputModel extends RouteElementModel { 2187 2188 @Override 2189 public boolean isInput() { 2190 return false; 2191 } 2192 2193 @Override 2194 public String getColumnName(int c) { 2195 if (c == STATE_COLUMN) { 2196 return rbx.getString("SetAction"); 2197 } 2198 return super.getColumnName(c); 2199 } 2200 2201 @Override 2202 public int getRowCount() { 2203 if (_showAllOutput) { 2204 return _outputList.size(); 2205 } else { 2206 return _includedOutputList.size(); 2207 } 2208 } 2209 2210 @Override 2211 public Object getValueAt(int r, int c) { 2212 ArrayList<RouteOutputElement> outputList; 2213 if (_showAllOutput) { 2214 outputList = _outputList; 2215 } else { 2216 outputList = _includedOutputList; 2217 } 2218 // some error checking 2219 if (r >= outputList.size()) { 2220 log.debug("row out of range"); 2221 return null; 2222 } 2223 switch (c) { 2224 case SNAME_COLUMN: // slot number 2225 return outputList.get(r).getSysName(); 2226 case UNAME_COLUMN: // 2227 return outputList.get(r).getUserName(); 2228 case INCLUDE_COLUMN: 2229 return outputList.get(r).isIncluded(); 2230 case TYPE_COLUMN: 2231 return outputList.get(r).getTypeString(); 2232 case STATE_COLUMN: // 2233 return outputList.get(r).getSetToState(); 2234 default: 2235 return null; 2236 } 2237 } 2238 2239 @Override 2240 public void setValueAt(Object type, int r, int c) { 2241 ArrayList<RouteOutputElement> outputList; 2242 if (_showAllOutput) { 2243 outputList = _outputList; 2244 } else { 2245 outputList = _includedOutputList; 2246 } 2247 switch (c) { 2248 case INCLUDE_COLUMN: 2249 outputList.get(r).setIncluded(((Boolean) type)); 2250 break; 2251 case STATE_COLUMN: 2252 outputList.get(r).setSetToState((String) type); 2253 break; 2254 default: 2255 log.warn("Unexpected column {} in setValueAt", c); 2256 break; 2257 } 2258 } 2259 } 2260 2261 /** 2262 * Table model for selecting output variables 2263 */ 2264 class AlignmentModel extends RouteElementModel { 2265 2266 @Override 2267 public boolean isInput() { 2268 return false; 2269 } 2270 2271 @Override 2272 public String getColumnName(int c) { 2273 if (c == STATE_COLUMN) { 2274 return rbx.getString("Alignment"); 2275 } 2276 return super.getColumnName(c); 2277 } 2278 2279 @Override 2280 public int getRowCount() { 2281 if (_showAllAlign) { 2282 return _alignList.size(); 2283 } else { 2284 return _includedAlignList.size(); 2285 } 2286 } 2287 2288 @Override 2289 public Object getValueAt(int r, int c) { 2290 ArrayList<AlignElement> alignList; 2291 if (_showAllAlign) { 2292 alignList = _alignList; 2293 } else { 2294 alignList = _includedAlignList; 2295 } 2296 // some error checking 2297 if (r >= alignList.size()) { 2298 log.debug("row out of range"); 2299 return null; 2300 } 2301 switch (c) { 2302 case SNAME_COLUMN: // slot number 2303 return alignList.get(r).getSysName(); 2304 case UNAME_COLUMN: // 2305 return alignList.get(r).getUserName(); 2306 case INCLUDE_COLUMN: 2307 return alignList.get(r).isIncluded(); 2308 case TYPE_COLUMN: 2309 return Bundle.getMessage("BeanNameSensor"); 2310 case STATE_COLUMN: // 2311 return alignList.get(r).getAlignType(); 2312 default: 2313 return null; 2314 } 2315 } 2316 2317 @Override 2318 public void setValueAt(Object type, int r, int c) { 2319 ArrayList<AlignElement> alignList; 2320 if (_showAllAlign) { 2321 alignList = _alignList; 2322 } else { 2323 alignList = _includedAlignList; 2324 } 2325 switch (c) { 2326 case INCLUDE_COLUMN: 2327 alignList.get(r).setIncluded(((Boolean) type)); 2328 break; 2329 case STATE_COLUMN: 2330 alignList.get(r).setAlignType((String) type); 2331 break; 2332 default: 2333 log.warn("Unexpected column {} in setValueAt", c); 2334 break; 2335 } 2336 } 2337 } 2338 2339 public final static String CONDITIONAL_USER_PREFIX = "Route "; 2340 2341 public final static int SENSOR_TYPE = 1; 2342 public final static int TURNOUT_TYPE = 2; 2343 public final static int LIGHT_TYPE = 3; 2344 public final static int SIGNAL_TYPE = 4; 2345 public final static int CONDITIONAL_TYPE = 5; 2346 public final static int ALL_TYPE = 6; 2347 2348 // Should not conflict with state variable types 2349 public final static int VETO = 0x80; 2350 // due to the unecessary bit assignments in SignalHead for appearances, 2351 // offset the following 2352 public static final int OFFSET = 0x30; 2353 public static final int SET_SIGNAL_HELD = Conditional.ACTION_SET_SIGNAL_HELD + OFFSET; 2354 public static final int CLEAR_SIGNAL_HELD = Conditional.ACTION_CLEAR_SIGNAL_HELD + OFFSET; 2355 public static final int SET_SIGNAL_DARK = Conditional.ACTION_SET_SIGNAL_DARK + OFFSET; 2356 public static final int SET_SIGNAL_LIT = Conditional.ACTION_SET_SIGNAL_LIT + OFFSET; 2357 2358 //private static int ROW_HEIGHT; 2359 private static final String ALIGN_SENSOR = rbx.getString("AlignSensor"); 2360 private static final String ALIGN_TURNOUT = rbx.getString("AlignTurnout"); 2361 private static final String ALIGN_LIGHT = rbx.getString("AlignLight"); 2362 private static final String ALIGN_SIGNAL = rbx.getString("AlignSignal"); 2363 private static final String ALIGN_ALL = rbx.getString("AlignAll"); 2364 2365 private static final String ON_CHANGE = Bundle.getMessage("OnConditionChange"); //rbx.getString("xOnChange"); 2366 private static final String ON_ACTIVE = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SensorStateActive"); //rbx.getString("xOnActive"); 2367 private static final String ON_INACTIVE = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SensorStateInactive"); //rbx.getString("xOnInactive"); 2368 private static final String VETO_ON_ACTIVE = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SensorStateActive"); //rbx.getString("xVetoActive"); 2369 private static final String VETO_ON_INACTIVE = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SensorStateInactive"); //rbx.getString("xVetoInactive"); 2370 private static final String ON_THROWN = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("TurnoutStateThrown"); //rbx.getString("xOnThrown"); 2371 private static final String ON_CLOSED = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("TurnoutStateClosed"); //rbx.getString("xOnClosed"); 2372 private static final String VETO_ON_THROWN = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("TurnoutStateThrown"); //rbx.getString("xVetoThrown"); 2373 private static final String VETO_ON_CLOSED = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("TurnoutStateClosed"); //rbx.getString("xVetoClosed"); 2374 private static final String ON_LIT = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("ColumnHeadLit"); //rbx.getString("xOnLit"); 2375 private static final String ON_UNLIT = rbx.getString("OnUnLit"); 2376 private static final String VETO_ON_LIT = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("ColumnHeadLit"); //rbx.getString("xVetoLit"); 2377 private static final String VETO_ON_UNLIT = rbx.getString("VetoUnLit"); 2378 private static final String ON_RED = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateRed"); //rbx.getString("xOnRed"); 2379 private static final String ON_FLASHRED = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingRed"); //rbx.getString("xOnFlashRed"); 2380 private static final String ON_YELLOW = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateYellow"); //rbx.getString("xOnYellow"); 2381 private static final String ON_FLASHYELLOW = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingYellow"); //rbx.getString("xOnFlashYellow"); 2382 private static final String ON_GREEN = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateGreen"); //rbx.getString("xOnGreen"); 2383 private static final String ON_FLASHGREEN = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingGreen"); //rbx.getString("xOnFlashGreen"); 2384 private static final String ON_DARK = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateDark"); //rbx.getString("xOnDark"); 2385 private static final String ON_SIGNAL_LIT = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("ColumnHeadLit"); //rbx.getString("xOnLit"); 2386 private static final String ON_SIGNAL_HELD = Bundle.getMessage("OnCondition") + " " + Bundle.getMessage("SignalHeadStateHeld"); //rbx.getString("xOnHeld"); 2387 private static final String VETO_ON_RED = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateRed"); //rbx.getString("xVetoOnRed"); 2388 private static final String VETO_ON_FLASHRED = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingRed"); //rbx.getString("xVetoOnFlashRed"); 2389 private static final String VETO_ON_YELLOW = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateYellow"); //rbx.getString("xVetoOnYellow"); 2390 private static final String VETO_ON_FLASHYELLOW = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingYellow"); //rbx.getString("xVetoOnFlashYellow"); 2391 private static final String VETO_ON_GREEN = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateGreen"); //rbx.getString("xVetoOnGreen"); 2392 private static final String VETO_ON_FLASHGREEN = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateFlashingGreen"); //rbx.getString("xVetoOnFlashGreen"); 2393 private static final String VETO_ON_DARK = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateDark"); //rbx.getString("xVetoOnDark"); 2394 private static final String VETO_ON_SIGNAL_LIT = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("ColumnHeadLit"); //rbx.getString("xVetoOnLit"); 2395 private static final String VETO_ON_SIGNAL_HELD = "Veto " + Bundle.getMessage("WhenCondition") + " " + Bundle.getMessage("SignalHeadStateHeld"); //rbx.getString("xVetoOnHeld"); 2396 2397 private static final String SET_TO_ACTIVE = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("SensorStateActive")); // rbx.getString("xSetActive"); 2398 private static final String SET_TO_INACTIVE = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("SensorStateInactive")); // rbx.getString("xSetInactive"); 2399 private static final String SET_TO_CLOSED = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameTurnout"), Bundle.getMessage("TurnoutStateClosed")); //rbx.getString("xSetClosed"); 2400 private static final String SET_TO_THROWN = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameTurnout"), Bundle.getMessage("TurnoutStateThrown")); //rbx.getString("xSetThrown"); 2401 private static final String SET_TO_TOGGLE = Bundle.getMessage("SetBeanState", "", Bundle.getMessage("Toggle")); 2402 private static final String SET_TO_ON = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameLight"), Bundle.getMessage("StateOn")); //rbx.getString("xSetLightOn"); 2403 private static final String SET_TO_OFF = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameLight"), Bundle.getMessage("StateOff")); //rbx.getString("xSetLightOff"); 2404 private static final String SET_TO_DARK = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateDark")); //rbx.getString("xSetDark"); 2405 private static final String SET_TO_LIT = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("ColumnHeadLit")); //rbx.getString("xSetLit"); 2406 private static final String SET_TO_HELD = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateHeld")); //rbx.getString("xSetHeld"); 2407 private static final String SET_TO_CLEAR = rbx.getString("SetClear"); 2408 private static final String SET_TO_RED = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateRed")); //rbx.getString("xSetRed"); 2409 private static final String SET_TO_FLASHRED = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingRed")); //rbx.getString("xSetFlashRed"); 2410 private static final String SET_TO_YELLOW = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateYellow")); //rbx.getString("xSetYellow"); 2411 private static final String SET_TO_FLASHYELLOW = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingYellow")); //rbx.getString("xSetFlashYellow"); 2412 private static final String SET_TO_GREEN = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateGreen")); //rbx.getString("xSetGreen"); 2413 private static final String SET_TO_FLASHGREEN = Bundle.getMessage("SetBeanState", Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingGreen")); //rbx.getString("xSetFlashGreen"); 2414 2415 private static String[] ALIGNMENT_STATES = new String[]{ALIGN_SENSOR, ALIGN_TURNOUT, ALIGN_LIGHT, ALIGN_SIGNAL, ALIGN_ALL}; 2416 private static String[] INPUT_SENSOR_STATES = new String[]{ON_ACTIVE, ON_INACTIVE, ON_CHANGE, VETO_ON_ACTIVE, VETO_ON_INACTIVE}; 2417 private static String[] INPUT_TURNOUT_STATES = new String[]{ON_THROWN, ON_CLOSED, ON_CHANGE, VETO_ON_THROWN, VETO_ON_CLOSED}; 2418 private static String[] INPUT_LIGHT_STATES = new String[]{ON_LIT, ON_UNLIT, ON_CHANGE, VETO_ON_LIT, VETO_ON_UNLIT}; 2419 private static String[] INPUT_SIGNAL_STATES = new String[]{ON_RED, ON_FLASHRED, ON_YELLOW, ON_FLASHYELLOW, ON_GREEN, 2420 ON_FLASHGREEN, ON_DARK, ON_SIGNAL_LIT, ON_SIGNAL_HELD, VETO_ON_RED, 2421 VETO_ON_FLASHRED, VETO_ON_YELLOW, VETO_ON_FLASHYELLOW, VETO_ON_GREEN, 2422 VETO_ON_FLASHGREEN, VETO_ON_DARK, VETO_ON_SIGNAL_LIT, VETO_ON_SIGNAL_HELD}; 2423 private static String[] OUTPUT_SENSOR_STATES = new String[]{SET_TO_ACTIVE, SET_TO_INACTIVE, SET_TO_TOGGLE}; 2424 private static String[] OUTPUT_TURNOUT_STATES = new String[]{SET_TO_CLOSED, SET_TO_THROWN, SET_TO_TOGGLE}; 2425 private static String[] OUTPUT_LIGHT_STATES = new String[]{SET_TO_ON, SET_TO_OFF, SET_TO_TOGGLE}; 2426 private static String[] OUTPUT_SIGNAL_STATES = new String[]{SET_TO_DARK, SET_TO_LIT, SET_TO_HELD, SET_TO_CLEAR, 2427 SET_TO_RED, SET_TO_FLASHRED, SET_TO_YELLOW, 2428 SET_TO_FLASHYELLOW, SET_TO_GREEN, SET_TO_FLASHGREEN}; 2429 2430 private static String getLogixSystemPrefix() { 2431 // Note: RouteExportToLogix uses ":RTX:" which is right? 2432 return InstanceManager.getDefault(LogixManager.class).getSystemNamePrefix() + ":RTX"; 2433 } 2434 2435 // should be private or package protected, but hey, its Logix! so its public 2436 // because Logix is scattered across all of JMRI without rhyme or reason 2437 public static String getLogixInitializer() { 2438 return getLogixSystemPrefix() + "INITIALIZER"; 2439 } 2440 2441 private String getConditionalSystemPrefix() { 2442 return getLogixSystemPrefix() + "C"; 2443 } 2444 2445 /** 2446 * Sorts RouteElement 2447 */ 2448 public static class RouteElementComparator implements java.util.Comparator<RouteElement> { 2449 // RouteElement objects aren't really NamedBeans, as they don't inherit 2450 // so we have to create our own comparator object here. This assumes they 2451 // the do have a named-bean-like system name format. 2452 RouteElementComparator() { 2453 } 2454 2455 static jmri.util.AlphanumComparator ac = new jmri.util.AlphanumComparator(); 2456 2457 @Override 2458 public int compare(RouteElement e1, RouteElement e2) { 2459 String s1 = e1.getSysName(); 2460 String s2 = e2.getSysName(); 2461 2462 int p1len = Manager.getSystemPrefixLength(s1); 2463 int p2len = Manager.getSystemPrefixLength(s2); 2464 2465 int comp = ac.compare(s1.substring(0, p1len), s2.substring(0, p2len)); 2466 if (comp != 0) return comp; 2467 2468 char c1 = s1.charAt(p1len); 2469 char c2 = s2.charAt(p2len); 2470 2471 if (c1 == c2) return ac.compare(s1.substring(p1len+1), s2.substring(p2len+1)); 2472 else return (c1 > c2) ? +1 : -1 ; 2473 } 2474 2475 } 2476 2477 /** 2478 * Base class for all the output (ConditionalAction) and input 2479 * (ConditionalVariable) elements 2480 */ 2481 static class RouteElement { 2482 2483 String _sysName; 2484 String _userName; 2485 int _type; 2486 String _typeString; 2487 boolean _included; 2488 int _state; 2489 2490 RouteElement(String sysName, String userName, int type) { 2491 _sysName = sysName; 2492 _userName = userName; 2493 _type = type; 2494 _included = false; 2495 switch (type) { 2496 case SENSOR_TYPE: 2497 _typeString = Bundle.getMessage("BeanNameSensor"); 2498 break; 2499 case TURNOUT_TYPE: 2500 _typeString = Bundle.getMessage("BeanNameTurnout"); 2501 break; 2502 case LIGHT_TYPE: 2503 _typeString = Bundle.getMessage("BeanNameLight"); 2504 break; 2505 case SIGNAL_TYPE: 2506 _typeString = Bundle.getMessage("BeanNameSignalHead"); 2507 break; 2508 case CONDITIONAL_TYPE: 2509 _typeString = Bundle.getMessage("BeanNameConditional"); 2510 break; 2511 default: 2512 log.warn("Unexpected type {} in RouteElement constructor", type); 2513 break; 2514 } 2515 } 2516 2517 String getSysName() { 2518 return _sysName; 2519 } 2520 2521 String getUserName() { 2522 return _userName; 2523 } 2524 2525 int getType() { 2526 return _type; 2527 } 2528 2529 String getTypeString() { 2530 return _typeString; 2531 } 2532 2533 boolean isIncluded() { 2534 return _included; 2535 } 2536 2537 void setIncluded(boolean include) { 2538 _included = include; 2539 } 2540 2541 int getState() { 2542 return _state; 2543 } 2544 2545 void setState(int state) { 2546 _state = state; 2547 } 2548 } 2549 2550 abstract class RouteInputElement extends RouteElement { 2551 2552 RouteInputElement(String sysName, String userName, int type) { 2553 super(sysName, userName, type); 2554 } 2555 2556 abstract String getTestState(); 2557 2558 abstract void setTestState(String state); 2559 } 2560 2561 class RouteInputSensor extends RouteInputElement { 2562 2563 RouteInputSensor(String sysName, String userName) { 2564 super(sysName, userName, SENSOR_TYPE); 2565 setState(Conditional.TYPE_SENSOR_ACTIVE); 2566 } 2567 2568 @Override 2569 String getTestState() { 2570 switch (_state) { 2571 case Conditional.TYPE_SENSOR_INACTIVE: 2572 return ON_INACTIVE; 2573 case Conditional.TYPE_SENSOR_ACTIVE: 2574 return ON_ACTIVE; 2575 case Route.ONCHANGE: 2576 return ON_CHANGE; 2577 case VETO + Conditional.TYPE_SENSOR_INACTIVE: 2578 return VETO_ON_INACTIVE; 2579 case VETO + Conditional.TYPE_SENSOR_ACTIVE: 2580 return VETO_ON_ACTIVE; 2581 default: 2582 log.error("Unhandled test state type: {}", _state); 2583 break; 2584 } 2585 return ""; 2586 } 2587 2588 @Override 2589 void setTestState(String state) { 2590 if (ON_INACTIVE.equals(state)) { 2591 _state = Conditional.TYPE_SENSOR_INACTIVE; 2592 } else if (ON_ACTIVE.equals(state)) { 2593 _state = Conditional.TYPE_SENSOR_ACTIVE; 2594 } else if (ON_CHANGE.equals(state)) { 2595 _state = Route.ONCHANGE; 2596 } else if (VETO_ON_INACTIVE.equals(state)) { 2597 _state = VETO + Conditional.TYPE_SENSOR_INACTIVE; 2598 } else if (VETO_ON_ACTIVE.equals(state)) { 2599 _state = VETO + Conditional.TYPE_SENSOR_ACTIVE; 2600 } 2601 } 2602 } 2603 2604 class RouteInputTurnout extends RouteInputElement { 2605 2606 RouteInputTurnout(String sysName, String userName) { 2607 super(sysName, userName, TURNOUT_TYPE); 2608 setState(Conditional.TYPE_TURNOUT_CLOSED); 2609 } 2610 2611 @Override 2612 String getTestState() { 2613 switch (_state) { 2614 case Conditional.TYPE_TURNOUT_CLOSED: 2615 return ON_CLOSED; 2616 case Conditional.TYPE_TURNOUT_THROWN: 2617 return ON_THROWN; 2618 case Route.ONCHANGE: 2619 return ON_CHANGE; 2620 case VETO + Conditional.TYPE_TURNOUT_CLOSED: 2621 return VETO_ON_CLOSED; 2622 case VETO + Conditional.TYPE_TURNOUT_THROWN: 2623 return VETO_ON_THROWN; 2624 default: 2625 log.warn("Unhandled test state type: {}", _state); 2626 } 2627 return ""; 2628 } 2629 2630 @Override 2631 void setTestState(String state) { 2632 if (ON_CLOSED.equals(state)) { 2633 _state = Conditional.TYPE_TURNOUT_CLOSED; 2634 } else if (ON_THROWN.equals(state)) { 2635 _state = Conditional.TYPE_TURNOUT_THROWN; 2636 } else if (ON_CHANGE.equals(state)) { 2637 _state = Route.ONCHANGE; 2638 } else if (VETO_ON_CLOSED.equals(state)) { 2639 _state = VETO + Conditional.TYPE_TURNOUT_CLOSED; 2640 } else if (VETO_ON_THROWN.equals(state)) { 2641 _state = VETO + Conditional.TYPE_TURNOUT_THROWN; 2642 } 2643 } 2644 } 2645 2646 class RouteInputLight extends RouteInputElement { 2647 2648 RouteInputLight(String sysName, String userName) { 2649 super(sysName, userName, LIGHT_TYPE); 2650 setState(Conditional.TYPE_LIGHT_OFF); 2651 } 2652 2653 @Override 2654 String getTestState() { 2655 switch (_state) { 2656 case Conditional.TYPE_LIGHT_OFF: 2657 return ON_UNLIT; 2658 case Conditional.TYPE_LIGHT_ON: 2659 return ON_LIT; 2660 case Route.ONCHANGE: 2661 return ON_CHANGE; 2662 case VETO + Conditional.TYPE_LIGHT_OFF: 2663 return VETO_ON_UNLIT; 2664 case VETO + Conditional.TYPE_LIGHT_ON: 2665 return VETO_ON_LIT; 2666 default: 2667 log.warn("Unhandled test state: {}", _state); 2668 break; 2669 } 2670 return ""; 2671 } 2672 2673 @Override 2674 void setTestState(String state) { 2675 if (ON_UNLIT.equals(state)) { 2676 _state = Conditional.TYPE_LIGHT_OFF; 2677 } else if (ON_LIT.equals(state)) { 2678 _state = Conditional.TYPE_LIGHT_ON; 2679 } else if (ON_CHANGE.equals(state)) { 2680 _state = Route.ONCHANGE; 2681 } else if (VETO_ON_UNLIT.equals(state)) { 2682 _state = VETO + Conditional.TYPE_LIGHT_OFF; 2683 } else if (VETO_ON_LIT.equals(state)) { 2684 _state = VETO + Conditional.TYPE_LIGHT_ON; 2685 } 2686 } 2687 } 2688 2689 class RouteInputSignal extends RouteInputElement { 2690 2691 RouteInputSignal(String sysName, String userName) { 2692 super(sysName, userName, SIGNAL_TYPE); 2693 setState(Conditional.TYPE_SIGNAL_HEAD_LIT); 2694 } 2695 2696 @Override 2697 String getTestState() { 2698 switch (_state) { 2699 case Conditional.TYPE_SIGNAL_HEAD_RED: 2700 return ON_RED; 2701 case Conditional.TYPE_SIGNAL_HEAD_FLASHRED: 2702 return ON_FLASHRED; 2703 case Conditional.TYPE_SIGNAL_HEAD_YELLOW: 2704 return ON_YELLOW; 2705 case Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW: 2706 return ON_FLASHYELLOW; 2707 case Conditional.TYPE_SIGNAL_HEAD_GREEN: 2708 return ON_GREEN; 2709 case Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN: 2710 return ON_FLASHGREEN; 2711 case Conditional.TYPE_SIGNAL_HEAD_DARK: 2712 return ON_DARK; 2713 case Conditional.TYPE_SIGNAL_HEAD_LIT: 2714 return ON_SIGNAL_LIT; 2715 case Conditional.TYPE_SIGNAL_HEAD_HELD: 2716 return ON_SIGNAL_HELD; 2717 case VETO + Conditional.TYPE_SIGNAL_HEAD_RED: 2718 return VETO_ON_RED; 2719 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHRED: 2720 return VETO_ON_FLASHRED; 2721 case VETO + Conditional.TYPE_SIGNAL_HEAD_YELLOW: 2722 return VETO_ON_YELLOW; 2723 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW: 2724 return VETO_ON_FLASHYELLOW; 2725 case VETO + Conditional.TYPE_SIGNAL_HEAD_GREEN: 2726 return VETO_ON_GREEN; 2727 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN: 2728 return VETO_ON_FLASHGREEN; 2729 case VETO + Conditional.TYPE_SIGNAL_HEAD_DARK: 2730 return VETO_ON_DARK; 2731 case VETO + Conditional.TYPE_SIGNAL_HEAD_LIT: 2732 return VETO_ON_SIGNAL_LIT; 2733 case VETO + Conditional.TYPE_SIGNAL_HEAD_HELD: 2734 return VETO_ON_SIGNAL_HELD; 2735 default: 2736 log.warn("Unhandled test state: {}", _state); 2737 break; 2738 } 2739 return ""; 2740 } 2741 2742 @Override 2743 void setTestState(String state) { 2744 if (ON_RED.equals(state)) { 2745 _state = Conditional.TYPE_SIGNAL_HEAD_RED; 2746 } else if (ON_FLASHRED.equals(state)) { 2747 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHRED; 2748 } else if (ON_YELLOW.equals(state)) { 2749 _state = Conditional.TYPE_SIGNAL_HEAD_YELLOW; 2750 } else if (ON_FLASHYELLOW.equals(state)) { 2751 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW; 2752 } else if (ON_GREEN.equals(state)) { 2753 _state = Conditional.TYPE_SIGNAL_HEAD_GREEN; 2754 } else if (ON_FLASHGREEN.equals(state)) { 2755 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN; 2756 } else if (ON_DARK.equals(state)) { 2757 _state = Conditional.TYPE_SIGNAL_HEAD_DARK; 2758 } else if (ON_SIGNAL_LIT.equals(state)) { 2759 _state = Conditional.TYPE_SIGNAL_HEAD_LIT; 2760 } else if (ON_SIGNAL_HELD.equals(state)) { 2761 _state = Conditional.TYPE_SIGNAL_HEAD_HELD; 2762 } else if (VETO_ON_RED.equals(state)) { 2763 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_RED; 2764 } else if (VETO_ON_FLASHRED.equals(state)) { 2765 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHRED; 2766 } else if (VETO_ON_YELLOW.equals(state)) { 2767 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_YELLOW; 2768 } else if (VETO_ON_FLASHYELLOW.equals(state)) { 2769 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW; 2770 } else if (VETO_ON_GREEN.equals(state)) { 2771 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_GREEN; 2772 } else if (VETO_ON_FLASHGREEN.equals(state)) { 2773 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN; 2774 } else if (VETO_ON_DARK.equals(state)) { 2775 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_DARK; 2776 } else if (VETO_ON_SIGNAL_LIT.equals(state)) { 2777 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_LIT; 2778 } else if (VETO_ON_SIGNAL_HELD.equals(state)) { 2779 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_HELD; 2780 } 2781 } 2782 } 2783 2784 abstract class RouteOutputElement extends RouteElement { 2785 2786 RouteOutputElement(String sysName, String userName, int type) { 2787 super(sysName, userName, type); 2788 } 2789 2790 abstract String getSetToState(); 2791 2792 abstract void setSetToState(String state); 2793 } 2794 2795 class RouteOutputSensor extends RouteOutputElement { 2796 2797 RouteOutputSensor(String sysName, String userName) { 2798 super(sysName, userName, SENSOR_TYPE); 2799 setState(Sensor.ACTIVE); 2800 } 2801 2802 @Override 2803 String getSetToState() { 2804 switch (_state) { 2805 case Sensor.INACTIVE: 2806 return SET_TO_INACTIVE; 2807 case Sensor.ACTIVE: 2808 return SET_TO_ACTIVE; 2809 case Route.TOGGLE: 2810 return SET_TO_TOGGLE; 2811 default: 2812 log.warn("Unhandled set to state: {}", _state); 2813 break; 2814 } 2815 return ""; 2816 } 2817 2818 @Override 2819 void setSetToState(String state) { 2820 if (SET_TO_INACTIVE.equals(state)) { 2821 _state = Sensor.INACTIVE; 2822 } else if (SET_TO_ACTIVE.equals(state)) { 2823 _state = Sensor.ACTIVE; 2824 } else if (SET_TO_TOGGLE.equals(state)) { 2825 _state = Route.TOGGLE; 2826 } 2827 } 2828 } 2829 2830 class RouteOutputTurnout extends RouteOutputElement { 2831 2832 RouteOutputTurnout(String sysName, String userName) { 2833 super(sysName, userName, TURNOUT_TYPE); 2834 setState(Turnout.CLOSED); 2835 } 2836 2837 @Override 2838 String getSetToState() { 2839 switch (_state) { 2840 case Turnout.CLOSED: 2841 return SET_TO_CLOSED; 2842 case Turnout.THROWN: 2843 return SET_TO_THROWN; 2844 case Route.TOGGLE: 2845 return SET_TO_TOGGLE; 2846 default: 2847 log.warn("Unhandled set to state: {}", _state); 2848 } 2849 return ""; 2850 } 2851 2852 @Override 2853 void setSetToState(String state) { 2854 if (SET_TO_CLOSED.equals(state)) { 2855 _state = Turnout.CLOSED; 2856 } else if (SET_TO_THROWN.equals(state)) { 2857 _state = Turnout.THROWN; 2858 } else if (SET_TO_TOGGLE.equals(state)) { 2859 _state = Route.TOGGLE; 2860 } 2861 } 2862 } 2863 2864 class RouteOutputLight extends RouteOutputElement { 2865 2866 RouteOutputLight(String sysName, String userName) { 2867 super(sysName, userName, LIGHT_TYPE); 2868 setState(Light.ON); 2869 } 2870 2871 @Override 2872 String getSetToState() { 2873 switch (_state) { 2874 case Light.ON: 2875 return SET_TO_ON; 2876 case Light.OFF: 2877 return SET_TO_OFF; 2878 case Route.TOGGLE: 2879 return SET_TO_TOGGLE; 2880 default: 2881 log.warn("Unhandled set to state: {}", _state); 2882 } 2883 return ""; 2884 } 2885 2886 @Override 2887 void setSetToState(String state) { 2888 if (SET_TO_ON.equals(state)) { 2889 _state = Light.ON; 2890 } else if (SET_TO_OFF.equals(state)) { 2891 _state = Light.OFF; 2892 } else if (SET_TO_TOGGLE.equals(state)) { 2893 _state = Route.TOGGLE; 2894 } 2895 } 2896 } 2897 2898 class RouteOutputSignal extends RouteOutputElement { 2899 2900 RouteOutputSignal(String sysName, String userName) { 2901 super(sysName, userName, SIGNAL_TYPE); 2902 setState(SignalHead.RED); 2903 } 2904 2905 @Override 2906 String getSetToState() { 2907 switch (_state) { 2908 case SignalHead.DARK: 2909 return SET_TO_DARK; 2910 case SignalHead.RED: 2911 return SET_TO_RED; 2912 case SignalHead.FLASHRED: 2913 return SET_TO_FLASHRED; 2914 case SignalHead.YELLOW: 2915 return SET_TO_YELLOW; 2916 case SignalHead.FLASHYELLOW: 2917 return SET_TO_FLASHYELLOW; 2918 case SignalHead.GREEN: 2919 return SET_TO_GREEN; 2920 case SignalHead.FLASHGREEN: 2921 return SET_TO_FLASHGREEN; 2922 case CLEAR_SIGNAL_HELD: 2923 return SET_TO_CLEAR; 2924 case SET_SIGNAL_LIT: 2925 return SET_TO_LIT; 2926 case SET_SIGNAL_HELD: 2927 return SET_TO_HELD; 2928 default: 2929 log.warn("Unhandled set to state: {}", _state); 2930 break; 2931 } 2932 return ""; 2933 } 2934 2935 @Override 2936 void setSetToState(String state) { 2937 if (SET_TO_DARK.equals(state)) { 2938 _state = SignalHead.DARK; 2939 } else if (SET_TO_RED.equals(state)) { 2940 _state = SignalHead.RED; 2941 } else if (SET_TO_FLASHRED.equals(state)) { 2942 _state = SignalHead.FLASHRED; 2943 } else if (SET_TO_YELLOW.equals(state)) { 2944 _state = SignalHead.YELLOW; 2945 } else if (SET_TO_FLASHYELLOW.equals(state)) { 2946 _state = SignalHead.FLASHYELLOW; 2947 } else if (SET_TO_GREEN.equals(state)) { 2948 _state = SignalHead.GREEN; 2949 } else if (SET_TO_FLASHGREEN.equals(state)) { 2950 _state = SignalHead.FLASHGREEN; 2951 } else if (SET_TO_CLEAR.equals(state)) { 2952 _state = CLEAR_SIGNAL_HELD; 2953 } else if (SET_TO_LIT.equals(state)) { 2954 _state = SET_SIGNAL_LIT; 2955 } else if (SET_TO_HELD.equals(state)) { 2956 _state = SET_SIGNAL_HELD; 2957 } 2958 } 2959 } 2960 2961 class AlignElement extends RouteElement { 2962 2963 AlignElement(String sysName, String userName) { 2964 super(sysName, userName, SENSOR_TYPE); 2965 setState(TURNOUT_TYPE); 2966 } 2967 2968 String getAlignType() { 2969 switch (_state) { 2970 case SENSOR_TYPE: 2971 return ALIGN_SENSOR; 2972 case TURNOUT_TYPE: 2973 return ALIGN_TURNOUT; 2974 case LIGHT_TYPE: 2975 return ALIGN_LIGHT; 2976 case SIGNAL_TYPE: 2977 return ALIGN_SIGNAL; 2978 case ALL_TYPE: 2979 return ALIGN_ALL; 2980 default: 2981 log.warn("Unhandled align type state: {}", _state); 2982 break; 2983 } 2984 return ""; 2985 } 2986 2987 void setAlignType(String state) { 2988 if (ALIGN_SENSOR.equals(state)) { 2989 _state = SENSOR_TYPE; 2990 } else if (ALIGN_TURNOUT.equals(state)) { 2991 _state = TURNOUT_TYPE; 2992 } else if (ALIGN_LIGHT.equals(state)) { 2993 _state = LIGHT_TYPE; 2994 } else if (ALIGN_SIGNAL.equals(state)) { 2995 _state = SIGNAL_TYPE; 2996 } else if (ALIGN_ALL.equals(state)) { 2997 _state = ALL_TYPE; 2998 } 2999 } 3000 } 3001 3002 @Override 3003 public void setMessagePreferencesDetails() { 3004 InstanceManager.getDefault(jmri.UserPreferencesManager.class).setPreferenceItemDetails(getClassName(), "remindSaveRoute", Bundle.getMessage("HideSaveReminder")); 3005 super.setMessagePreferencesDetails(); 3006 } 3007 3008 @Override 3009 protected String getClassName() { 3010 return LRouteTableAction.class.getName(); 3011 } 3012 3013 @Override 3014 public String getClassDescription() { 3015 return Bundle.getMessage("TitleLRouteTable"); 3016 } 3017 3018 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LRouteTableAction.class); 3019}