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