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.*; 010 011import javax.annotation.CheckForNull; 012import javax.annotation.Nonnull; 013import javax.swing.*; 014import javax.swing.table.AbstractTableModel; 015import javax.swing.table.TableColumn; 016import javax.swing.table.TableColumnModel; 017 018import jmri.Conditional.Operator; 019import jmri.*; 020import jmri.implementation.DefaultConditionalAction; 021import jmri.script.swing.ScriptFileChooser; 022import jmri.util.FileUtil; 023import jmri.util.JmriJFrame; 024import jmri.util.swing.JmriJOptionPane; 025 026/** 027 * Swing action to create and register groups of Logix Condtionals to perform a 028 * railroad control task. 029 * 030 * @author Pete Cressman Copyright (C) 2009 031 * @author Egbert Broerse i18n 2016 032 * 033 */ 034public class LRouteTableAction extends AbstractTableAction<Logix> { 035 036 static final ResourceBundle rbx = ResourceBundle.getBundle("jmri.jmrit.beantable.LRouteTableBundle"); 037 038 /** 039 * Create an action with a specific title. 040 * <p> 041 * Note that the argument is the Action title, not the title of the 042 * resulting frame. Perhaps this should be changed? 043 * 044 * @param s title of the action 045 */ 046 public LRouteTableAction(String s) { 047 super(s); 048 _logixManager = InstanceManager.getNullableDefault(LogixManager.class); 049 _conditionalManager = InstanceManager.getNullableDefault(ConditionalManager.class); 050 // disable ourself if there is no Logix manager or no Conditional manager available 051 if ((_logixManager == null) || (_conditionalManager == null)) { 052 setEnabled(false); 053 } 054 _systemName.setName("hwAddressTextField"); // for GUI test 055 _userName.setName("userNameTextField"); // for GUI Test 056 } 057 058 public LRouteTableAction() { 059 this(Bundle.getMessage("TitleLRouteTable")); 060 } 061 062 /** 063 * Create the JTable DataModel, along with the changes for the specific case 064 * of Road Conditionals. 065 */ 066 @Override 067 protected void createModel() { 068 m = new LBeanTableDataModel(); 069 } 070 071 class LBeanTableDataModel extends BeanTableDataModel<Logix> { 072 073 // overlay the value column with the enable column 074 // overlay the delete column with the edit column 075 public static final int ENABLECOL = VALUECOL; 076 public static final int EDITCOL = DELETECOL; 077 078 /** 079 * Override to filter out the LRoutes from the rest of Logix. 080 */ 081 @Override 082 protected synchronized void updateNameList() { 083 // first, remove listeners from the individual objects 084 if (sysNameList != null) { 085 for (int i = 0; i < sysNameList.size(); i++) { 086 // if object has been deleted, it's not here; ignore it 087 NamedBean b = getBySystemName(sysNameList.get(i)); 088 if (b != null) { 089 b.removePropertyChangeListener(this); 090 } 091 } 092 } 093 sysNameList = new ArrayList<>(); 094 // and add them back in 095 getManager().getNamedBeanSet().forEach(b -> { 096 if (b.getSystemName().startsWith(getLogixSystemPrefix())) { 097 sysNameList.add(b.getSystemName()); 098 b.addPropertyChangeListener(this); 099 } 100 }); 101 log.debug("updateNameList: sysNameList size= {}", sysNameList.size()); 102 } 103 104 @Override 105 public String getColumnName(int col) { 106 switch (col) { 107 case EDITCOL: 108 return ""; // no heading on "Edit" 109 case ENABLECOL: 110 return Bundle.getMessage("ColumnHeadEnabled"); 111 default: 112 return super.getColumnName(col); 113 } 114 } 115 116 @Override 117 public Class<?> getColumnClass(int col) { 118 switch (col) { 119 case EDITCOL: 120 return JButton.class; 121 case ENABLECOL: 122 return Boolean.class; 123 default: 124 return super.getColumnClass(col); 125 } 126 } 127 128 @Override 129 public int getPreferredWidth(int col) { 130 // override default value for SystemName and UserName columns 131 switch (col) { 132 case SYSNAMECOL: 133 return new JTextField(20).getPreferredSize().width; 134 case USERNAMECOL: 135 case COMMENTCOL: 136 return new JTextField(25).getPreferredSize().width; 137 case EDITCOL: 138 // not actually used due to the configDeleteColumn, setColumnToHoldButton, configureButton 139 return new JTextField(Bundle.getMessage("ButtonEdit")).getPreferredSize().width+4; 140 case ENABLECOL: 141 // not actually used due to the configValueColumn, setColumnToHoldButton, configureButton 142 return new JTextField(5).getPreferredSize().width; 143 default: 144 return super.getPreferredWidth(col); 145 } 146 } 147 148 @Override 149 public boolean isCellEditable(int row, int col) { 150 switch (col) { 151 case EDITCOL: 152 case ENABLECOL: 153 return true; 154 default: 155 return super.isCellEditable(row, col); 156 } 157 } 158 159 @Override 160 public Object getValueAt(int row, int col) { 161 switch (col) { 162 case EDITCOL: 163 return Bundle.getMessage("ButtonEdit"); 164 case ENABLECOL: 165 return ((Logix) getValueAt(row, SYSNAMECOL)).getEnabled(); 166 default: 167 return super.getValueAt(row, col); 168 } 169 } 170 171 @Override 172 public void setValueAt(Object value, int row, int col) { 173 switch (col) { 174 case EDITCOL: 175 // set up to edit 176 String sName = ((Logix) getValueAt(row, SYSNAMECOL)).getSystemName(); 177 editPressed(sName); 178 break; 179 case ENABLECOL: 180 // alternate 181 Logix x = (Logix) getValueAt(row, SYSNAMECOL); 182 boolean v = x.getEnabled(); 183 x.setEnabled(!v); 184 break; 185 default: 186 super.setValueAt(value, row, col); 187 break; 188 } 189 } 190 191 /** 192 * Delete the bean after all the checking has been done. 193 * <p> 194 * Deactivate the Logix and remove its conditionals. 195 */ 196 @Override 197 protected void doDelete(Logix logix) { 198 if (logix != null) { 199 logix.deActivateLogix(); 200 // delete the Logix and all its Conditionals 201 _logixManager.deleteLogix(logix); 202 } 203 } 204 205 @Override 206 protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) { 207 if (Logix.PROPERTY_ENABLED.equals(e.getPropertyName())) { 208 return true; 209 } else { 210 return super.matchPropertyName(e); 211 } 212 } 213 214 @Override 215 public Manager<Logix> getManager() { 216 return _logixManager; 217 } 218 219 @Override 220 public Logix getBySystemName(@Nonnull String name) { 221 return _logixManager.getBySystemName(name); 222 } 223 224 @Override 225 public Logix getByUserName(@Nonnull String name) { 226 return _logixManager.getByUserName(name); 227 } 228 229 /*public int getDisplayDeleteMsg() { return InstanceManager.getDefault(jmri.UserPreferencesManager.class).getMultipleChoiceOption(getClassName(),"delete"); } 230 public void setDisplayDeleteMsg(int boo) { InstanceManager.getDefault(jmri.UserPreferencesManager.class).setMultipleChoiceOption(getClassName(), "delete", boo); }*/ 231 @Override 232 protected String getMasterClassName() { 233 return getClassName(); 234 } 235 236 @Override 237 public void configureTable(JTable table) { 238 table.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer()); 239 table.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer()); 240 table.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor()); 241 super.configureTable(table); 242 } 243 244 // Not needed - here for interface compatibility 245 @Override 246 public void clickOn(Logix t) { 247 } 248 249 @Override 250 public String getValue(String s) { 251 return ""; 252 } 253 254 // typical to get correct width 255 @Override 256 protected void configDeleteColumn(JTable table) { 257 // have the DELETECOL = EDITCOL column hold a button 258 setColumnToHoldButton(table, DELETECOL, 259 new JButton(Bundle.getMessage("ButtonEdit"))); 260 } 261 262 @Override 263 protected void configValueColumn(JTable table) { 264 } 265 266 @Override 267 protected String getBeanType() { 268 return "LRoute"; 269 } 270 271 } 272 273 @Override 274 protected void setTitle() { 275 f.setTitle(Bundle.getMessage("TitleLRouteTable")); 276 } 277 278 @Override 279 protected String helpTarget() { 280 return "package.jmri.jmrit.beantable.LRouteTable"; 281 } 282 283///////////////////////////////////// Edit window ////////////////////////////// 284 private ConditionalManager _conditionalManager = null; 285 private LogixManager _logixManager = null; 286 287 private JTextField _systemName = new JTextField(15); 288 private JTextField _userName = new JTextField(25); 289 290 JmriJFrame _addFrame = null; 291 private JTabbedPane _tabbedPane = null; 292 293 private RouteInputModel _inputModel; 294 private JComboBox<String> _testStateCombo; 295 private JRadioButton _inputAllButton; 296 private boolean _showAllInput; 297 298 private RouteOutputModel _outputModel; 299 private JComboBox<String> _setStateCombo; 300 private JRadioButton _outputAllButton; 301 private boolean _showAllOutput; 302 303 private AlignmentModel _alignModel; 304 private JRadioButton _alignAllButton; 305 private boolean _showAllAlign; 306 307 private JCheckBox _lockCheckBox; 308 private boolean _lock = false; 309 310 private JPanel _typePanel; 311 private JRadioButton _newRouteButton; 312 private boolean _newRouteType = true; 313 private JRadioButton _initializeButton; 314 private boolean _initialize = false; 315 316 private JTextField soundFile = new JTextField(30); 317 private JTextField scriptFile = new JTextField(30); 318 319 private JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); 320 private JButton createButton = new JButton(Bundle.getMessage("ButtonCreate")); 321 private JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 322 private JButton updateButton = new JButton(Bundle.getMessage("ButtonUpdate")); 323 324 private boolean routeDirty = false; // true to fire reminder to save work 325 private boolean checkEnabled = 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 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 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 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 SignalHeadManager shm = InstanceManager.getDefault(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 private 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 private 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 private 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 private 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( e -> { 893 _newRouteType = true; 894 _systemName.setEnabled(true); 895 }); 896 oldRoute.setToolTipText(rbx.getString("OldRouteHint")); 897 oldRoute.addActionListener( e -> { 898 _newRouteType = false; 899 _systemName.setEnabled(true); 900 }); 901 _initializeButton.setToolTipText(rbx.getString("InitializeHint")); 902 _initializeButton.addActionListener( 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( e -> updatePressed()); 933 updateButton.setToolTipText(rbx.getString("UpdateHint")); 934 updateButton.setName("UpdateButton"); 935 936 // Show the initial buttons, and hide the others 937 cancelButton.setVisible(true); 938 updateButton.setVisible(false); 939 createButton.setVisible(false); 940 deleteButton.setVisible(false); 941 tab1.add(pb); 942 943 tab1.setVisible(true); 944 _tabbedPane.addTab(rbx.getString("BasicTab"), null, tab1, rbx.getString("BasicTabHint")); 945 946 //////////////////////////////////// Tab 2 ///////////////////////////// 947 JPanel tab2 = new JPanel(); 948 tab2.setLayout(new BoxLayout(tab2, BoxLayout.Y_AXIS)); 949 tab2.add(new JLabel(rbx.getString("OutputTitle") + ":")); 950 _outputAllButton = new JRadioButton(Bundle.getMessage("All"), true); 951 JRadioButton includedOutputButton = new JRadioButton(Bundle.getMessage("Included"), false); 952 tab2.add(makeShowButtons(_outputAllButton, includedOutputButton, null, Bundle.getMessage("Show") + ":")); 953 _outputAllButton.addActionListener( e -> { 954 // Setup for display of all Turnouts, if needed 955 if (!_showAllOutput) { 956 _showAllOutput = true; 957 _outputModel.fireTableDataChanged(); 958 } 959 }); 960 includedOutputButton.addActionListener( e -> { 961 // Setup for display of included Turnouts only, if needed 962 if (_showAllOutput) { 963 _showAllOutput = false; 964 initializeIncludedOutputList(); 965 _outputModel.fireTableDataChanged(); 966 } 967 }); 968 tab2.add(new JLabel(rbx.getString("PickOutput"))); 969 970 _outputModel = new RouteOutputModel(); 971 JTable routeOutputTable = new JTable(_outputModel); 972 JScrollPane _outputScrollPane = makeColumns(routeOutputTable, _setStateCombo, true); 973 tab2.add(_outputScrollPane, BorderLayout.CENTER); 974 tab2.setVisible(true); 975 _tabbedPane.addTab(rbx.getString("ActionTab"), null, tab2, rbx.getString("ActionTabHint")); 976 977 //////////////////////////////////// Tab 3 ///////////////////////////// 978 JPanel tab3 = new JPanel(); 979 tab3.setLayout(new BoxLayout(tab3, BoxLayout.Y_AXIS)); 980 tab3.add(new JLabel(rbx.getString("InputTitle") + ":")); 981 _inputAllButton = new JRadioButton(Bundle.getMessage("All"), true); 982 JRadioButton includedInputButton = new JRadioButton(Bundle.getMessage("Included"), false); 983 tab3.add(makeShowButtons(_inputAllButton, includedInputButton, null, Bundle.getMessage("Show") + ":")); 984 _inputAllButton.addActionListener( e -> { 985 // Setup for display of all Turnouts, if needed 986 if (!_showAllInput) { 987 _showAllInput = true; 988 _inputModel.fireTableDataChanged(); 989 } 990 }); 991 includedInputButton.addActionListener( e -> { 992 // Setup for display of included Turnouts only, if needed 993 if (_showAllInput) { 994 _showAllInput = false; 995 initializeIncludedInputList(); 996 _inputModel.fireTableDataChanged(); 997 } 998 }); 999 tab3.add(new JLabel(rbx.getString("PickInput"))); 1000 1001 _inputModel = new RouteInputModel(); 1002 JTable routeInputTable = new JTable(_inputModel); 1003 //ROW_HEIGHT = routeInputTable.getRowHeight(); 1004 JScrollPane _inputScrollPane = makeColumns(routeInputTable, _testStateCombo, true); 1005 tab3.add(_inputScrollPane, BorderLayout.CENTER); 1006 tab3.setVisible(true); 1007 _tabbedPane.addTab(rbx.getString("TriggerTab"), null, tab3, rbx.getString("TriggerTabHint")); 1008 1009 ////////////////////// Tab 4 ///////////////// 1010 JPanel tab4 = new JPanel(); 1011 tab4.setLayout(new BoxLayout(tab4, BoxLayout.Y_AXIS)); 1012 tab4.add(new JLabel(rbx.getString("MiscTitle") + ":")); 1013 // Enter filenames for sound, script 1014 JPanel p25 = new JPanel(); 1015 p25.setLayout(new FlowLayout()); 1016 p25.add(new JLabel(Bundle.getMessage("LabelPlaySound"))); 1017 JButton ss = new JButton("..."); 1018 ss.addActionListener( e -> setSoundPressed()); 1019 p25.add(ss); 1020 p25.add(soundFile); 1021 tab4.add(p25); 1022 1023 p25 = new JPanel(); 1024 p25.setLayout(new FlowLayout()); 1025 p25.add(new JLabel(Bundle.getMessage("LabelRunScript"))); 1026 ss = new JButton("..."); 1027 ss.addActionListener( e -> setScriptPressed()); 1028 p25.add(ss); 1029 p25.add(scriptFile); 1030 tab4.add(p25); 1031 1032 p25 = new JPanel(); 1033 p25.setLayout(new FlowLayout()); 1034 p25.add(new JLabel(rbx.getString("SetLocks") + ":")); 1035 _lockCheckBox = new JCheckBox(rbx.getString("Lock"), true); 1036 _lockCheckBox.addActionListener( e -> { 1037 // Setup for display of all Turnouts, if needed 1038 _lock = _lockCheckBox.isSelected(); 1039 }); 1040 p25.add(_lockCheckBox); 1041 tab4.add(p25); 1042 1043 _alignAllButton = new JRadioButton(Bundle.getMessage("All"), true); 1044 JRadioButton includedAlignButton = new JRadioButton(Bundle.getMessage("Included"), false); 1045 tab4.add(makeShowButtons(_alignAllButton, includedAlignButton, null, Bundle.getMessage("Show") + ":")); 1046 _alignAllButton.addActionListener( e -> { 1047 // Setup for display of all Turnouts, if needed 1048 if (!_showAllAlign) { 1049 _showAllAlign = true; 1050 _alignModel.fireTableDataChanged(); 1051 } 1052 }); 1053 includedAlignButton.addActionListener( e -> { 1054 // Setup for display of included Turnouts only, if needed 1055 if (_showAllAlign) { 1056 _showAllAlign = false; 1057 initializeIncludedAlignList(); 1058 _alignModel.fireTableDataChanged(); 1059 } 1060 }); 1061 tab4.add(new JLabel(rbx.getString("PickAlign"))); 1062 _alignModel = new AlignmentModel(); 1063 JTable alignTable = new JTable(_alignModel); 1064 JComboBox<String> _alignCombo = new JComboBox<>(); 1065 for (String state : ALIGNMENT_STATES) { 1066 _alignCombo.addItem(state); 1067 } 1068 JScrollPane alignScrollPane = makeColumns(alignTable, _alignCombo, false); 1069 //alignTable.setPreferredScrollableViewportSize(new java.awt.Dimension(250,200)); 1070 _alignCombo = new JComboBox<>(); 1071 for (String state : ALIGNMENT_STATES) { 1072 _alignCombo.addItem(state); 1073 } 1074 tab4.add(alignScrollPane, BorderLayout.CENTER); 1075 tab4.setVisible(true); 1076 _tabbedPane.addTab(rbx.getString("MiscTab"), null, tab4, rbx.getString("MiscTabHint")); 1077 1078 Container contentPane = _addFrame.getContentPane(); 1079 //tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); 1080 1081 /////////////////////////////////// 1082 JPanel pt = new JPanel(); 1083 pt.add(_tabbedPane); 1084 contentPane.add(pt); 1085 1086 // set listener for window closing 1087 _addFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1088 @Override 1089 public void windowClosing(java.awt.event.WindowEvent e) { 1090 // remind to save, if Route was created or edited 1091 if (routeDirty) { 1092 showReminderMessage(); 1093 } 1094 clearPage(); 1095 _addFrame.setVisible(false); 1096 _inputModel.dispose(); 1097 _outputModel.dispose(); 1098 routeDirty = false; 1099 } 1100 }); 1101 1102 _addFrame.pack(); 1103 _inputAllButton.doClick(); 1104 _outputAllButton.doClick(); 1105 _alignAllButton.doClick(); 1106 _newRouteButton.doClick(); 1107 if (_initialize) { 1108 _initializeButton.doClick(); 1109 } 1110 } else { 1111 _addFrame.setVisible(true); 1112 } 1113 } 1114 1115 private void showReminderMessage() { 1116 if (checkEnabled) { 1117 return; 1118 } 1119 InstanceManager.getDefault(UserPreferencesManager.class). 1120 showInfoMessage(Bundle.getMessage("ReminderTitle"), Bundle.getMessage("ReminderSaveString", Bundle.getMessage("BeanNameLRoute")), 1121 getClassName(), 1122 "remindSaveRoute"); // NOI18N 1123 } 1124 1125 /* 1126 * Utility for addPressed 1127 */ 1128 private JPanel makeShowButtons(JRadioButton allButton, JRadioButton includeButton, 1129 JRadioButton extraButton, String msg) { 1130 JPanel panel = new JPanel(); 1131 panel.add(new JLabel(msg)); 1132 panel.add(allButton); 1133 panel.add(includeButton); 1134 ButtonGroup selGroup = new ButtonGroup(); 1135 selGroup.add(allButton); 1136 selGroup.add(includeButton); 1137 if (extraButton != null) { 1138 panel.add(extraButton); 1139 selGroup.add(extraButton); 1140 } 1141 return panel; 1142 } 1143 1144 /* 1145 * Utility for addPressed 1146 */ 1147 private JScrollPane makeColumns(@Nonnull JTable table, JComboBox<String> box, boolean specialBox) { 1148 table.setRowSelectionAllowed(false); 1149 //table.setPreferredScrollableViewportSize(new java.awt.Dimension(250,450)); 1150 TableColumnModel columnModel = table.getColumnModel(); 1151 1152 TableColumn sNameColumnT = columnModel.getColumn(RouteElementModel.SNAME_COLUMN); 1153 sNameColumnT.setResizable(true); 1154 sNameColumnT.setMinWidth(75); 1155 //sNameColumnT.setMaxWidth(110); 1156 1157 TableColumn uNameColumnT = columnModel.getColumn(RouteElementModel.UNAME_COLUMN); 1158 uNameColumnT.setResizable(true); 1159 uNameColumnT.setMinWidth(75); 1160 //uNameColumnT.setMaxWidth(260); 1161 1162 TableColumn typeColumnT = columnModel.getColumn(RouteElementModel.TYPE_COLUMN); 1163 typeColumnT.setResizable(true); 1164 typeColumnT.setMinWidth(50); 1165 //typeColumnT.setMaxWidth(110); 1166 1167 TableColumn includeColumnT = columnModel.getColumn(RouteElementModel.INCLUDE_COLUMN); 1168 includeColumnT.setResizable(false); 1169 includeColumnT.setMinWidth(30); 1170 includeColumnT.setMaxWidth(60); 1171 1172 TableColumn stateColumnT = columnModel.getColumn(RouteElementModel.STATE_COLUMN); 1173 if (specialBox) { 1174 box = new JComboBox<>(); 1175 stateColumnT.setCellEditor(new ComboBoxCellEditor(box)); 1176 } else { 1177 stateColumnT.setCellEditor(new DefaultCellEditor(box)); 1178 } 1179 stateColumnT.setResizable(false); 1180 stateColumnT.setMinWidth(75); 1181 //stateColumnT.setMaxWidth(1310); 1182 1183 return new JScrollPane(table); 1184 } 1185 1186 /** 1187 * Initialize list of included input elements 1188 */ 1189 private void initializeIncludedInputList() { 1190 _includedInputList = new ArrayList<>(); 1191 for (int i = 0; i < _inputList.size(); i++) { 1192 if (_inputList.get(i).isIncluded()) { 1193 _includedInputList.add(_inputList.get(i)); 1194 } 1195 } 1196 } 1197 1198 /** 1199 * Initialize list of included input elements 1200 */ 1201 private void initializeIncludedOutputList() { 1202 _includedOutputList = new ArrayList<>(); 1203 for (int i = 0; i < _outputList.size(); i++) { 1204 if (_outputList.get(i).isIncluded()) { 1205 _includedOutputList.add(_outputList.get(i)); 1206 } 1207 } 1208 } 1209 1210 /** 1211 * Initialize list of included alignment sensors 1212 */ 1213 private void initializeIncludedAlignList() { 1214 _includedAlignList = new ArrayList<>(); 1215 for (int i = 0; i < _alignList.size(); i++) { 1216 if (_alignList.get(i).isIncluded()) { 1217 _includedAlignList.add(_alignList.get(i)); 1218 } 1219 } 1220 } 1221 1222 private ArrayList<RouteOutputElement> makeTurnoutLockList() { 1223 ArrayList<RouteOutputElement> list = new ArrayList<>(); 1224 for (int i = 0; i < _outputList.size(); i++) { 1225 if (_outputList.get(i).isIncluded()) { 1226 RouteOutputElement elt = _outputList.get(i); 1227 if ((elt.getType() == TURNOUT_TYPE) && (elt.getState() != Route.TOGGLE)) { 1228 list.add(elt); 1229 } 1230 } 1231 } 1232 return list; 1233 } 1234 1235 private void showMessage(String msg) { 1236 1237 JmriJOptionPane.showMessageDialog( 1238 _addFrame, rbx.getString(msg), Bundle.getMessage("WarningTitle"), 1239 JmriJOptionPane.WARNING_MESSAGE); 1240 } 1241 1242 private boolean checkNewNamesOK() { 1243 // Get system name and user name 1244 String sName = _systemName.getText(); 1245 if (sName.length() == 0 || sName.equals(getLogixSystemPrefix())) { 1246 showMessage("EnterNames"); 1247 return false; 1248 } 1249 if (!sName.startsWith(getLogixSystemPrefix())) { 1250 sName = getLogixSystemPrefix() + sName; 1251 } 1252 // check if a Route with this system name already exists 1253 if (_logixManager.getBySystemName(sName) != null) { 1254 // Route already exists 1255 showMessage("DuplicateSys"); 1256 updateButton.setVisible(true); 1257 return false; 1258 } 1259 String uName = _userName.getText(); 1260 // check if a Route with the same user name exists 1261 if (!uName.isEmpty()) { 1262 if (_logixManager.getByUserName(uName) != null) { 1263 // Route with this user name already exists 1264 showMessage("DuplicateUser"); 1265 updateButton.setVisible(true); 1266 return false; 1267 } else { 1268 return true; 1269 } 1270 } 1271 _systemName.setText(sName); 1272 return true; 1273 } 1274 1275 @CheckForNull 1276 private Logix checkNamesOK() { 1277 // Get system name and user name 1278 String sName = _systemName.getText(); 1279 if (sName.length() == 0) { 1280 showMessage("EnterNames"); 1281 return null; 1282 } 1283 Logix logix = _logixManager.getBySystemName(sName); 1284 if (!sName.startsWith(getLogixSystemPrefix())) { 1285 sName = getLogixSystemPrefix() + sName; 1286 } 1287 if (logix != null) { 1288 return logix; 1289 } 1290 String uName = _userName.getText(); 1291 if (uName.length() != 0) { 1292 logix = _logixManager.getByUserName(uName); 1293 if (logix != null) { 1294 return logix; 1295 } 1296 } 1297 logix = _logixManager.createNewLogix(sName, uName); 1298 if (logix == null) { 1299 // should never get here 1300 log.error("Unknown failure to create Route with System Name: {}", sName); 1301 } 1302 return logix; 1303 } 1304 1305 private JFileChooser soundChooser = null; 1306 1307 /** 1308 * Set the sound file 1309 */ 1310 private void setSoundPressed() { 1311 if (soundChooser == null) { 1312 soundChooser = new jmri.util.swing.JmriJFileChooser(FileUtil.getUserFilesPath()); 1313 soundChooser.setFileFilter(new jmri.util.NoArchiveFileFilter()); 1314 } 1315 soundChooser.rescanCurrentDirectory(); 1316 int retVal = soundChooser.showOpenDialog(null); 1317 // handle selection or cancel 1318 if (retVal == JFileChooser.APPROVE_OPTION) { 1319 try { 1320 soundFile.setText(FileUtil.getPortableFilename(soundChooser.getSelectedFile().getCanonicalPath())); 1321 } catch (java.io.IOException e) { 1322 log.error("exception setting sound file", e); 1323 } 1324 } 1325 } 1326 1327 private ScriptFileChooser scriptChooser = null; 1328 1329 /** 1330 * Set the script file 1331 */ 1332 private void setScriptPressed() { 1333 if (scriptChooser == null) { 1334 scriptChooser = new ScriptFileChooser(); 1335 } 1336 scriptChooser.rescanCurrentDirectory(); 1337 int retVal = scriptChooser.showOpenDialog(null); 1338 // handle selection or cancel 1339 if (retVal == JFileChooser.APPROVE_OPTION) { 1340 try { 1341 scriptFile.setText(FileUtil.getPortableFilename(scriptChooser.getSelectedFile().getCanonicalPath())); 1342 } catch (java.io.IOException e) { 1343 log.error("exception setting script file", e); 1344 } 1345 } 1346 } 1347 1348 /** 1349 * Responds to the Add Route button. 1350 * 1351 * @param e the action event 1352 */ 1353 void createPressed(ActionEvent e) { 1354 if (!checkNewNamesOK()) { 1355 return; 1356 } 1357 updatePressed(); 1358 } 1359 1360 /** 1361 * Responds to the Delete button. 1362 * 1363 * @param e the action event 1364 */ 1365 private void deletePressed(ActionEvent e) { 1366 Logix l = checkNamesOK(); 1367 if (l != null) { 1368 l.deActivateLogix(); 1369 // delete the Logix and all its Conditionals 1370 _logixManager.deleteLogix(l); 1371 } 1372 finishUpdate(); 1373 } 1374 1375 /** 1376 * Update the Route Table. 1377 */ 1378 private void updatePressed() { 1379 Logix logix = checkNamesOK(); 1380 if (logix == null) { 1381 log.error("No Logix found!"); 1382 return; 1383 } 1384 String sName = logix.getSystemName(); 1385 // Check if the User Name has been changed 1386 String uName = _userName.getText(); 1387 logix.setUserName(uName); 1388 1389 initializeIncludedInputList(); 1390 initializeIncludedOutputList(); 1391 initializeIncludedAlignList(); 1392 log.debug("updatePressed: _includedInputList.size()= {}, _includedOutputList.size()= {}, _includedAlignList.size()= {}", 1393 _includedInputList.size(), _includedOutputList.size(), _includedAlignList.size()); 1394 1395 ////// Construct output actions for trigger conditionals /////////// 1396 ArrayList<ConditionalAction> actionList = new ArrayList<>(); 1397 for (int i = 0; i < _includedOutputList.size(); i++) { 1398 RouteOutputElement elt = _includedOutputList.get(i); 1399 String name = elt.getUserName(); 1400 if (name == null || name.length() == 0) { 1401 name = elt.getSysName(); 1402 } 1403 int state = elt.getState(); // actionData 1404 Conditional.Action actionType = Conditional.Action.NONE; 1405 String params = ""; 1406 switch (elt.getType()) { 1407 case SENSOR_TYPE: 1408 actionType = Conditional.Action.SET_SENSOR; 1409 break; 1410 case TURNOUT_TYPE: 1411 actionType = Conditional.Action.SET_TURNOUT; 1412 break; 1413 case LIGHT_TYPE: 1414 actionType = Conditional.Action.SET_LIGHT; 1415 break; 1416 case SIGNAL_TYPE: 1417 actionType = Conditional.Action.SET_SIGNAL_APPEARANCE; 1418 if (state > OFFSET) { 1419 actionType = Conditional.Action.getOperatorFromIntValue(state & ~OFFSET); 1420 } 1421 break; 1422 default: 1423 log.debug("updatePressed: Unknown action type {}", elt.getType()); 1424 } 1425 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1426 actionType, name, state, params)); 1427 } 1428 String file = scriptFile.getText(); 1429 if (file.length() > 0) { 1430 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1431 Conditional.Action.RUN_SCRIPT, "", -1, file)); 1432 } 1433 file = soundFile.getText(); 1434 if (file.length() > 0) { 1435 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1436 Conditional.Action.PLAY_SOUND, "", -1, file)); 1437 } 1438 ArrayList<ConditionalAction> onChangeList = cloneActionList(actionList, Conditional.ACTION_OPTION_ON_CHANGE); 1439 1440 /////// Construct 'AND' clause from 'VETO' controls //////// 1441 ArrayList<ConditionalVariable> vetoList = new ArrayList<>(); 1442 if (!_initialize) { 1443 for (int i = 0; i < _includedInputList.size(); i++) { 1444 RouteInputElement elt = _includedInputList.get(i); 1445 String name = elt.getUserName(); 1446 if (name == null || name.length() == 0) { 1447 name = elt.getSysName(); 1448 } 1449 Operator opern = ( i == 0 ? Conditional.Operator.NONE : Conditional.Operator.AND); 1450 int state = elt.getState(); 1451 if (VETO < state) { 1452 vetoList.add(new ConditionalVariable(true, opern, 1453 Conditional.Type.getOperatorFromIntValue(state & ~VETO), name, _newRouteType)); 1454 } 1455 } 1456 } 1457 1458 ///////////////// Make Trigger Conditional Controls ///////////////// 1459 ArrayList<ConditionalVariable> oneTriggerList = new ArrayList<>(); 1460 ArrayList<ConditionalVariable> twoTriggerList = new ArrayList<>(); 1461 if (!_initialize) { 1462 for (int i = 0; i < _includedInputList.size(); i++) { 1463 RouteInputElement elt = _includedInputList.get(i); 1464 String name = elt.getUserName(); 1465 if (name == null || name.length() == 0) { 1466 name = elt.getSysName(); 1467 } 1468 Operator opern = _newRouteType ? Conditional.Operator.OR : Conditional.Operator.AND; 1469 if (i == 0) { 1470 opern = Conditional.Operator.NONE; 1471 } 1472 int type = elt.getState(); 1473 if (VETO > type) { 1474 if (Route.ONCHANGE == type) { 1475 switch (elt.getType()) { 1476 case SENSOR_TYPE: 1477 type = Conditional.TYPE_SENSOR_ACTIVE; 1478 break; 1479 case TURNOUT_TYPE: 1480 type = Conditional.TYPE_TURNOUT_CLOSED; 1481 break; 1482 case LIGHT_TYPE: 1483 type = Conditional.TYPE_LIGHT_ON; 1484 break; 1485 case SIGNAL_TYPE: 1486 type = Conditional.TYPE_SIGNAL_HEAD_LIT; 1487 break; 1488 default: 1489 log.debug("updatePressed: Unknown state variable type {}", elt.getType()); 1490 } 1491 twoTriggerList.add(new ConditionalVariable(false, opern, 1492 Conditional.Type.getOperatorFromIntValue(type), name, true)); 1493 } else { 1494 oneTriggerList.add(new ConditionalVariable(false, opern, 1495 Conditional.Type.getOperatorFromIntValue(type), name, true)); 1496 } 1497 } 1498 } 1499 if (actionList.isEmpty()) { 1500 JmriJOptionPane.showMessageDialog( 1501 _addFrame, rbx.getString("noAction"), 1502 rbx.getString("addErr"), JmriJOptionPane.ERROR_MESSAGE); 1503 return; 1504 } 1505 } else { 1506 oneTriggerList.add(new ConditionalVariable(false, Conditional.Operator.NONE, 1507 Conditional.Type.NONE, getLogixInitializer(), true)); 1508 } 1509 log.debug("actionList.size()= {}, oneTriggerList.size()= {}, twoTriggerList.size()= {}, " 1510 + "onChangeList.size()= {}, vetoList.size()= {}", 1511 actionList.size(), oneTriggerList.size(), twoTriggerList.size(), onChangeList.size(), vetoList.size()); 1512 1513 logix.deActivateLogix(); 1514 1515 // remove old Conditionals for actions (ver 2.5.2 only -remove a bad idea) 1516 char[] ch = sName.toCharArray(); 1517 int hash = 0; 1518 for (int i = 0; i < ch.length; i++) { 1519 hash += ch[i]; 1520 } 1521 String cSystemName = getConditionalSystemPrefix() + "T" + hash; 1522 removeConditionals(cSystemName, logix); 1523 cSystemName = getConditionalSystemPrefix() + "F" + hash; 1524 removeConditionals(cSystemName, logix); 1525 cSystemName = getConditionalSystemPrefix() + "A" + hash; 1526 removeConditionals(cSystemName, logix); 1527 cSystemName = getConditionalSystemPrefix() + "L" + hash; 1528 removeConditionals(cSystemName, logix); 1529 int n = 0; 1530 do { 1531 n++; 1532 cSystemName = sName + n + "A"; 1533 } while (removeConditionals(cSystemName, logix)); 1534 n = 0; 1535 do { 1536 n++; 1537 cSystemName = sName + n + "T"; 1538 } while (removeConditionals(cSystemName, logix)); 1539 cSystemName = sName + "L"; 1540 removeConditionals(cSystemName, logix); 1541 1542 int numConds = 1; 1543 if (_newRouteType) { 1544 numConds = makeRouteConditional(numConds, /*false,*/ actionList, oneTriggerList, 1545 vetoList, logix, sName, uName, "T"); 1546 if (!_initialize && !twoTriggerList.isEmpty()) { 1547 numConds = makeRouteConditional(numConds, /*true, actionList,*/ onChangeList, twoTriggerList, 1548 null, logix, sName, uName, "T"); 1549 } 1550 } else { 1551 for (int i = 0; i < oneTriggerList.size(); i++) { 1552 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1553 vList.add(oneTriggerList.get(i)); 1554 numConds = makeRouteConditional(numConds, /*false,*/ actionList, vList, 1555 vetoList, logix, sName, uName, "T"); 1556 } 1557 for (int i = 0; i < twoTriggerList.size(); i++) { 1558 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1559 vList.add(twoTriggerList.get(i)); 1560 numConds = makeRouteConditional(numConds, /*true, actionList,*/ onChangeList, vList, 1561 vetoList, logix, sName, uName, "T"); 1562 } 1563 } 1564 if (numConds == 1) { 1565 JmriJOptionPane.showMessageDialog( 1566 _addFrame, rbx.getString("noVars"), 1567 rbx.getString("addErr"), JmriJOptionPane.ERROR_MESSAGE); 1568 return; 1569 } 1570 1571 ///////////////// Make Alignment Conditionals ////////////////////////// 1572 numConds = 1; 1573 for (int i = 0; i < _includedAlignList.size(); i++) { 1574 ArrayList<ConditionalVariable> vList = new ArrayList<>(); 1575 ArrayList<ConditionalAction> aList = new ArrayList<>(); 1576 AlignElement sensor = _includedAlignList.get(i); 1577 String name = sensor.getUserName(); 1578 if (name == null || name.length() == 0) { 1579 name = sensor.getSysName(); 1580 } 1581 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1582 Conditional.Action.SET_SENSOR, name, Sensor.ACTIVE, "")); 1583 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE, 1584 Conditional.Action.SET_SENSOR, name, Sensor.INACTIVE, "")); 1585 int alignType = sensor.getState(); 1586 for (int k = 0; k < _includedOutputList.size(); k++) { 1587 RouteOutputElement elt = _includedOutputList.get(k); 1588 Conditional.Type varType = Conditional.Type.NONE; 1589 boolean add = (ALL_TYPE == alignType); 1590 switch (elt.getType()) { 1591 case SENSOR_TYPE: 1592 if (alignType == SENSOR_TYPE) { 1593 add = true; 1594 } 1595 switch (elt.getState()) { 1596 case Sensor.INACTIVE: 1597 varType = Conditional.Type.SENSOR_INACTIVE; 1598 break; 1599 case Sensor.ACTIVE: 1600 varType = Conditional.Type.SENSOR_ACTIVE; 1601 break; 1602 case Route.TOGGLE: 1603 add = false; 1604 break; 1605 default: 1606 log.warn("Unexpected state {} from elt.getState() in SENSOR_TYPE", elt.getState()); 1607 break; 1608 } 1609 break; 1610 case TURNOUT_TYPE: 1611 if (alignType == TURNOUT_TYPE) { 1612 add = true; 1613 } 1614 switch (elt.getState()) { 1615 case Turnout.CLOSED: 1616 varType = Conditional.Type.TURNOUT_CLOSED; 1617 break; 1618 case Turnout.THROWN: 1619 varType = Conditional.Type.TURNOUT_THROWN; 1620 break; 1621 case Route.TOGGLE: 1622 add = false; 1623 break; 1624 default: 1625 log.warn("Unexpected state {} from elt.getState() in TURNOUT_TYPE", elt.getState()); 1626 break; 1627 } 1628 break; 1629 case LIGHT_TYPE: 1630 if (alignType == LIGHT_TYPE) { 1631 add = true; 1632 } 1633 switch (elt.getState()) { 1634 case Light.ON: 1635 varType = Conditional.Type.LIGHT_ON; 1636 break; 1637 case Light.OFF: 1638 varType = Conditional.Type.LIGHT_OFF; 1639 break; 1640 case Route.TOGGLE: 1641 add = false; 1642 break; 1643 default: 1644 log.warn("Unexpected state {} from elt.getState() in LIGHT_TYPE", elt.getState()); 1645 break; 1646 } 1647 break; 1648 case SIGNAL_TYPE: 1649 if (alignType == SIGNAL_TYPE) { 1650 add = true; 1651 } 1652 switch (elt.getState()) { 1653 case SET_SIGNAL_DARK: 1654 case SignalHead.DARK: 1655 varType = Conditional.Type.SIGNAL_HEAD_DARK; 1656 break; 1657 case SignalHead.RED: 1658 varType = Conditional.Type.SIGNAL_HEAD_RED; 1659 break; 1660 case SignalHead.FLASHRED: 1661 varType = Conditional.Type.SIGNAL_HEAD_FLASHRED; 1662 break; 1663 case SignalHead.YELLOW: 1664 varType = Conditional.Type.SIGNAL_HEAD_YELLOW; 1665 break; 1666 case SignalHead.FLASHYELLOW: 1667 varType = Conditional.Type.SIGNAL_HEAD_FLASHYELLOW; 1668 break; 1669 case SignalHead.GREEN: 1670 varType = Conditional.Type.SIGNAL_HEAD_GREEN; 1671 break; 1672 case SignalHead.FLASHGREEN: 1673 varType = Conditional.Type.SIGNAL_HEAD_FLASHGREEN; 1674 break; 1675 case SET_SIGNAL_HELD: 1676 varType = Conditional.Type.SIGNAL_HEAD_HELD; 1677 break; 1678 case CLEAR_SIGNAL_HELD: 1679 add = false; // don't know how to test for this 1680 break; 1681 case SET_SIGNAL_LIT: 1682 varType = Conditional.Type.SIGNAL_HEAD_LIT; 1683 break; 1684 default: 1685 log.warn("Unexpected state {} from elt.getState() in SIGNAL_TYPE", elt.getState()); 1686 break; 1687 } 1688 break; 1689 default: 1690 log.debug("updatePressed: Unknown Alignment state variable type {}", elt.getType()); 1691 } 1692 if (add && !_initialize) { 1693 String eltName = elt.getUserName(); 1694 if (eltName == null || eltName.length() == 0) { 1695 eltName = elt.getSysName(); 1696 } 1697 vList.add(new ConditionalVariable(false, Conditional.Operator.AND, 1698 varType, eltName, true)); 1699 } 1700 } 1701 if (!vList.isEmpty()) { 1702 numConds = makeAlignConditional(numConds, aList, vList, logix, sName, uName); 1703 } else { 1704 JmriJOptionPane.showMessageDialog( 1705 _addFrame, java.text.MessageFormat.format(rbx.getString("NoAlign"), 1706 new Object[]{name, sensor.getAlignType()}), 1707 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 1708 } 1709 } 1710 ///////////////// Make Lock Conditional ////////////////////////// 1711 if (_lock) { 1712 ArrayList<ConditionalAction> aList = new ArrayList<>(); 1713 for (int k = 0; k < _includedOutputList.size(); k++) { 1714 RouteOutputElement elt = _includedOutputList.get(k); 1715 if (elt.getType() != TURNOUT_TYPE || elt.getState() == Route.TOGGLE) { 1716 continue; 1717 } 1718 String eltName = elt.getUserName(); 1719 if (eltName == null || eltName.length() == 0) { 1720 eltName = elt.getSysName(); 1721 } 1722 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 1723 Conditional.Action.LOCK_TURNOUT, 1724 eltName, Turnout.LOCKED, "")); 1725 aList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE, 1726 Conditional.Action.LOCK_TURNOUT, 1727 eltName, Turnout.UNLOCKED, "")); 1728 } 1729 makeRouteConditional(numConds, /*false,*/ aList, oneTriggerList, 1730 vetoList, logix, sName, uName, "L"); 1731 } 1732 log.debug("Conditionals added= {}", logix.getNumConditionals()); 1733 for (int i = 0; i < logix.getNumConditionals(); i++) { 1734 log.debug("Conditional SysName= \"{}\"", logix.getConditionalByNumberOrder(i)); 1735 } 1736 logix.activateLogix(); 1737 log.debug("Conditionals added= {}", logix.getNumConditionals()); 1738 for (int i = 0; i < logix.getNumConditionals(); i++) { 1739 log.debug("Conditional SysName= \"{}\"", logix.getConditionalByNumberOrder(i)); 1740 } 1741 finishUpdate(); 1742 } //updatePressed 1743 1744 private boolean removeConditionals(String cSystemName, Logix logix) { 1745 Conditional c = _conditionalManager.getBySystemName(cSystemName); 1746 if (c != null) { 1747 logix.deleteConditional(cSystemName); 1748 return true; 1749 } 1750 return false; 1751 } 1752 1753 /** 1754 * Create a new Route conditional. 1755 * 1756 * @param numConds number of existing route conditionals 1757 * @param actionList actions to take in conditional 1758 * @param triggerList triggers for conditional to take actions 1759 * @param vetoList controls that veto taking actions 1760 * @param logix Logix to add the conditional to 1761 * @param sName system name for conditional 1762 * @param uName user name for conditional 1763 * @param type type of conditional 1764 * @return number of conditionals after the creation 1765 * @throws IllegalArgumentException if "user input no good" 1766 */ 1767 private int makeRouteConditional(int numConds, /*boolean onChange,*/ ArrayList<ConditionalAction> actionList, 1768 ArrayList<ConditionalVariable> triggerList, ArrayList<ConditionalVariable> vetoList, 1769 Logix logix, String sName, String uName, String type) { 1770 if (log.isDebugEnabled()) { 1771 log.debug("makeRouteConditional: numConds= {}, triggerList.size()= {}", numConds, triggerList.size()); 1772 } 1773 if (triggerList.isEmpty() && (vetoList == null || vetoList.isEmpty())) { 1774 return numConds; 1775 } 1776 StringBuilder antecedent = new StringBuilder(); 1777 ArrayList<ConditionalVariable> varList = new ArrayList<>(); 1778 1779 int tSize = triggerList.size(); 1780 if (tSize > 0) { 1781 if (tSize > 1) { 1782 antecedent.append("("); 1783 } 1784 antecedent.append("R1"); // NOI18N 1785 for (int i = 1; i < tSize; i++) { 1786 antecedent.append(" ").append(Bundle.getMessage("LogicOR")).append(" R").append(i + 1); // NOI18N 1787 } 1788 if (tSize > 1) { 1789 antecedent.append(")"); 1790 } 1791 for (int i = 0; i < triggerList.size(); i++) { 1792 //varList.add(cloneVariable(triggerList.get(i))); 1793 varList.add(triggerList.get(i)); 1794 } 1795 } 1796 1797 if (vetoList != null && !vetoList.isEmpty()) { 1798 int vSize = vetoList.size(); 1799 if (tSize > 0) { 1800 antecedent.append(" ").append(Bundle.getMessage("LogicAND")).append(" "); 1801 } 1802 if (vSize > 1) { 1803 antecedent.append("("); 1804 } 1805 antecedent.append(Bundle.getMessage("LogicNOT")).append(" R").append(1 + tSize); // NOI18N 1806 for (int i = 1; i < vSize; i++) { 1807 antecedent.append(" ").append(Bundle.getMessage("LogicAND")).append(" ").append(Bundle.getMessage("LogicNOT")).append(" R").append(i + 1 + tSize); // NOI18N 1808 } 1809 if (vSize > 1) { 1810 antecedent.append(")"); 1811 } 1812 for (int i = 0; i < vetoList.size(); i++) { 1813 //varList.add(cloneVariable(vetoList.get(i))); 1814 varList.add(vetoList.get(i)); 1815 } 1816 } 1817 String cSystemName = sName + numConds + type; 1818 String cUserName = CONDITIONAL_USER_PREFIX + numConds + "C " + uName; 1819 Conditional c = null; 1820 try { 1821 c = _conditionalManager.createNewConditional(cSystemName, cUserName); 1822 } catch (Exception ex) { 1823 // user input no good 1824 handleCreateException(sName); 1825 // throw without creating any 1826 throw new IllegalArgumentException("user input no good"); 1827 } 1828 c.setStateVariables(varList); 1829 //int option = onChange ? Conditional.ACTION_OPTION_ON_CHANGE : Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE; 1830 //c.setAction(cloneActionList(actionList, option)); 1831 c.setAction(actionList); 1832 Conditional.AntecedentOperator logicType = 1833 _newRouteType 1834 ? Conditional.AntecedentOperator.MIXED 1835 : Conditional.AntecedentOperator.ALL_AND; 1836 c.setLogicType(logicType, antecedent.toString()); 1837 logix.addConditional(cSystemName, 0); 1838 log.debug("Conditional added: SysName= \"{}\"", cSystemName); 1839 c.calculate(true, null); 1840 1841 return numConds + 1; 1842 } 1843 1844 private void handleCreateException(String sysName) { 1845 JmriJOptionPane.showMessageDialog(_addFrame, 1846 Bundle.getMessage("ErrorLRouteAddFailed", sysName) + "\n" + Bundle.getMessage("ErrorAddFailedCheck"), 1847 Bundle.getMessage("ErrorTitle"), 1848 JmriJOptionPane.ERROR_MESSAGE); 1849 } 1850 1851 /** 1852 * Create a new alignment conditional. 1853 * 1854 * @param numConds number of existing route conditionals 1855 * @param actionList actions to take in conditional 1856 * @param triggerList triggers for conditional to take actions 1857 * @param logix Logix to add the conditional to 1858 * @param sName system name for conditional 1859 * @param uName user name for conditional 1860 * @return number of conditionals after the creation 1861 * @throws IllegalArgumentException if "user input no good" 1862 */ 1863 private int makeAlignConditional(int numConds, ArrayList<ConditionalAction> actionList, 1864 ArrayList<ConditionalVariable> triggerList, 1865 Logix logix, String sName, String uName) { 1866 if (triggerList.isEmpty()) { 1867 return numConds; 1868 } 1869 String cSystemName = sName + numConds + "A"; 1870 String cUserName = CONDITIONAL_USER_PREFIX + numConds + "A " + uName; 1871 Conditional c = null; 1872 try { 1873 c = _conditionalManager.createNewConditional(cSystemName, cUserName); 1874 } catch (Exception ex) { 1875 // user input no good 1876 handleCreateException(sName); 1877 // throw without creating any 1878 throw new IllegalArgumentException("user input no good"); 1879 } 1880 c.setStateVariables(triggerList); 1881 //c.setAction(cloneActionList(actionList, Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE)); 1882 c.setAction(actionList); 1883 c.setLogicType(Conditional.AntecedentOperator.ALL_AND, ""); 1884 logix.addConditional(cSystemName, 0); 1885 log.debug("Conditional added: SysName= \"{}\"", cSystemName); 1886 c.calculate(true, null); 1887 return numConds+1; 1888 } 1889 1890 @Nonnull 1891 private ArrayList<ConditionalAction> cloneActionList(ArrayList<ConditionalAction> actionList, int option) { 1892 ArrayList<ConditionalAction> list = new ArrayList<>(); 1893 for (int i = 0; i < actionList.size(); i++) { 1894 ConditionalAction action = actionList.get(i); 1895 ConditionalAction clone = new DefaultConditionalAction(); 1896 clone.setType(action.getType()); 1897 clone.setOption(option); 1898 clone.setDeviceName(action.getDeviceName()); 1899 clone.setActionData(action.getActionData()); 1900 clone.setActionString(action.getActionString()); 1901 list.add(clone); 1902 } 1903 return list; 1904 } 1905 1906 private void finishUpdate() { 1907 routeDirty = true; 1908 clearPage(); 1909 } 1910 1911 private void clearPage() { 1912 // move to show all turnouts if not there 1913 cancelIncludedOnly(); 1914 deleteButton.setVisible(false); 1915 cancelButton.setVisible(false); 1916 updateButton.setVisible(false); 1917 createButton.setVisible(false); 1918 _systemName.setText(""); 1919 _userName.setText(""); 1920 soundFile.setText(""); 1921 scriptFile.setText(""); 1922 for (int i = _inputList.size() - 1; i >= 0; i--) { 1923 _inputList.get(i).setIncluded(false); 1924 } 1925 for (int i = _outputList.size() - 1; i >= 0; i--) { 1926 _outputList.get(i).setIncluded(false); 1927 } 1928 for (int i = _alignList.size() - 1; i >= 0; i--) { 1929 _alignList.get(i).setIncluded(false); 1930 } 1931 _lock = false; 1932 _newRouteType = true; 1933 _newRouteButton.doClick(); 1934 _lockCheckBox.setSelected(_lock); 1935 if (routeDirty) { 1936 showReminderMessage(); 1937 routeDirty = false; 1938 } 1939 _addFrame.setVisible(false); 1940 } 1941 1942 /** 1943 * Cancels included only option 1944 */ 1945 private void cancelIncludedOnly() { 1946 if (!_showAllInput) { 1947 _inputAllButton.doClick(); 1948 } 1949 if (!_showAllOutput) { 1950 _outputAllButton.doClick(); 1951 } 1952 if (!_showAllAlign) { 1953 _alignAllButton.doClick(); 1954 } 1955 } 1956 1957////////////////////////////// Internal Utility Classes //////////////////////////////// 1958 private class ComboBoxCellEditor extends DefaultCellEditor { 1959 1960 ComboBoxCellEditor() { 1961 super(new JComboBox<String>()); 1962 } 1963 1964 ComboBoxCellEditor(JComboBox<String> comboBox) { 1965 super(comboBox); 1966 } 1967 1968 @SuppressWarnings("unchecked") // getComponent call requires an unchecked cast 1969 @Override 1970 public Component getTableCellEditorComponent(JTable table, Object value, 1971 boolean isSelected, int row, int column) { 1972 1973 RouteElementModel model = (RouteElementModel) table.getModel(); 1974 1975 RouteElement elt; 1976 String[] items; 1977 if (model.isInput()) { 1978 if (_showAllInput) { 1979 elt = _inputList.get(row); 1980 } else { 1981 elt = _includedInputList.get(row); 1982 } 1983 items = getInputComboBoxItems(elt.getType()); 1984 } else { 1985 if (_showAllOutput) { 1986 elt = _outputList.get(row); 1987 } else { 1988 elt = _includedOutputList.get(row); 1989 } 1990 items = getOutputComboBoxItems(elt.getType()); 1991 } 1992 JComboBox<String> comboBox = (JComboBox<String>) getComponent(); 1993 comboBox.removeAllItems(); 1994 for (String item : items) { 1995 comboBox.addItem(item); 1996 } 1997 return super.getTableCellEditorComponent(table, value, isSelected, row, column); 1998 } 1999 2000 private String[] getInputComboBoxItems(int type) { 2001 switch (type) { 2002 case SENSOR_TYPE: 2003 return INPUT_SENSOR_STATES; 2004 case TURNOUT_TYPE: 2005 return INPUT_TURNOUT_STATES; 2006 case LIGHT_TYPE: 2007 return INPUT_LIGHT_STATES; 2008 case SIGNAL_TYPE: 2009 return INPUT_SIGNAL_STATES; 2010 default: 2011 log.warn("Unhandled object type: {}", type); 2012 break; 2013 } 2014 return new String[]{}; 2015 } 2016 2017 private String[] getOutputComboBoxItems(int type) { 2018 switch (type) { 2019 case SENSOR_TYPE: 2020 return OUTPUT_SENSOR_STATES; 2021 case TURNOUT_TYPE: 2022 return OUTPUT_TURNOUT_STATES; 2023 case LIGHT_TYPE: 2024 return OUTPUT_LIGHT_STATES; 2025 case SIGNAL_TYPE: 2026 return OUTPUT_SIGNAL_STATES; 2027 default: 2028 log.warn("Unhandled type: {}", type); 2029 } 2030 return new String[]{}; 2031 } 2032 2033 } 2034 2035 /** 2036 * Base Table model for selecting Route elements 2037 */ 2038 abstract class RouteElementModel extends AbstractTableModel implements PropertyChangeListener { 2039 2040 abstract boolean isInput(); 2041 2042 @Override 2043 public Class<?> getColumnClass(int c) { 2044 if (c == INCLUDE_COLUMN) { 2045 return Boolean.class; 2046 } else { 2047 return String.class; 2048 } 2049 } 2050 2051 @Override 2052 public int getColumnCount() { 2053 return 5; 2054 } 2055 2056 @Override 2057 public String getColumnName(int c) { 2058 switch (c) { 2059 case SNAME_COLUMN: 2060 return Bundle.getMessage("ColumnSystemName"); 2061 case UNAME_COLUMN: 2062 return Bundle.getMessage("ColumnUserName"); 2063 case TYPE_COLUMN: 2064 return rbx.getString("Type"); 2065 case INCLUDE_COLUMN: 2066 return Bundle.getMessage("Include"); 2067 default: 2068 log.warn("Unhandled column type: {}", c); 2069 break; 2070 } 2071 return ""; 2072 } 2073 2074 @Override 2075 public boolean isCellEditable(int r, int c) { 2076 return ((c == INCLUDE_COLUMN) || (c == STATE_COLUMN)); 2077 } 2078 2079 @Override 2080 public void propertyChange(java.beans.PropertyChangeEvent e) { 2081 if ( Manager.PROPERTY_LENGTH.equals( e.getPropertyName())) { 2082 // a new NamedBean is available in the manager 2083 fireTableDataChanged(); 2084 } 2085 } 2086 2087 public void dispose() { 2088 InstanceManager.turnoutManagerInstance().removePropertyChangeListener(this); 2089 } 2090 2091 public static final int SNAME_COLUMN = 0; 2092 public static final int UNAME_COLUMN = 1; 2093 public static final int TYPE_COLUMN = 2; 2094 public static final int INCLUDE_COLUMN = 3; 2095 public static final int STATE_COLUMN = 4; 2096 } 2097 2098 /** 2099 * Table model for selecting input variables 2100 */ 2101 private class RouteInputModel extends RouteElementModel { 2102 2103 @Override 2104 public boolean isInput() { 2105 return true; 2106 } 2107 2108 @Override 2109 public String getColumnName(int c) { 2110 if (c == STATE_COLUMN) { 2111 return rbx.getString("SetTrigger"); 2112 } 2113 return super.getColumnName(c); 2114 } 2115 2116 @Override 2117 public int getRowCount() { 2118 if (_showAllInput) { 2119 return _inputList.size(); 2120 } else { 2121 return _includedInputList.size(); 2122 } 2123 } 2124 2125 @Override 2126 public Object getValueAt(int r, int c) { 2127 ArrayList<RouteInputElement> inputList; 2128 if (_showAllInput) { 2129 inputList = _inputList; 2130 } else { 2131 inputList = _includedInputList; 2132 } 2133 // some error checking 2134 if (r >= inputList.size()) { 2135 log.debug("row out of range"); 2136 return null; 2137 } 2138 switch (c) { 2139 case SNAME_COLUMN: 2140 return inputList.get(r).getSysName(); 2141 case UNAME_COLUMN: 2142 return inputList.get(r).getUserName(); 2143 case TYPE_COLUMN: 2144 return inputList.get(r).getTypeString(); 2145 case INCLUDE_COLUMN: 2146 return inputList.get(r).isIncluded(); 2147 case STATE_COLUMN: 2148 return inputList.get(r).getTestState(); 2149 default: 2150 return null; 2151 } 2152 } 2153 2154 @Override 2155 public void setValueAt(Object type, int r, int c) { 2156 ArrayList<RouteInputElement> inputList; 2157 if (_showAllInput) { 2158 inputList = _inputList; 2159 } else { 2160 inputList = _includedInputList; 2161 } 2162 switch (c) { 2163 case INCLUDE_COLUMN: 2164 inputList.get(r).setIncluded(((Boolean) type)); 2165 break; 2166 case STATE_COLUMN: 2167 inputList.get(r).setTestState((String) type); 2168 break; 2169 default: 2170 log.warn("Unexpected column {} in setValueAt", c); 2171 break; 2172 } 2173 } 2174 } 2175 2176 /** 2177 * Table model for selecting output variables 2178 */ 2179 private class RouteOutputModel extends RouteElementModel { 2180 2181 @Override 2182 public boolean isInput() { 2183 return false; 2184 } 2185 2186 @Override 2187 public String getColumnName(int c) { 2188 if (c == STATE_COLUMN) { 2189 return rbx.getString("SetAction"); 2190 } 2191 return super.getColumnName(c); 2192 } 2193 2194 @Override 2195 public int getRowCount() { 2196 if (_showAllOutput) { 2197 return _outputList.size(); 2198 } else { 2199 return _includedOutputList.size(); 2200 } 2201 } 2202 2203 @Override 2204 public Object getValueAt(int r, int c) { 2205 ArrayList<RouteOutputElement> outputList; 2206 if (_showAllOutput) { 2207 outputList = _outputList; 2208 } else { 2209 outputList = _includedOutputList; 2210 } 2211 // some error checking 2212 if (r >= outputList.size()) { 2213 log.debug("row out of range"); 2214 return null; 2215 } 2216 switch (c) { 2217 case SNAME_COLUMN: // slot number 2218 return outputList.get(r).getSysName(); 2219 case UNAME_COLUMN: // 2220 return outputList.get(r).getUserName(); 2221 case INCLUDE_COLUMN: 2222 return outputList.get(r).isIncluded(); 2223 case TYPE_COLUMN: 2224 return outputList.get(r).getTypeString(); 2225 case STATE_COLUMN: // 2226 return outputList.get(r).getSetToState(); 2227 default: 2228 return null; 2229 } 2230 } 2231 2232 @Override 2233 public void setValueAt(Object type, int r, int c) { 2234 ArrayList<RouteOutputElement> outputList; 2235 if (_showAllOutput) { 2236 outputList = _outputList; 2237 } else { 2238 outputList = _includedOutputList; 2239 } 2240 switch (c) { 2241 case INCLUDE_COLUMN: 2242 outputList.get(r).setIncluded(((Boolean) type)); 2243 break; 2244 case STATE_COLUMN: 2245 outputList.get(r).setSetToState((String) type); 2246 break; 2247 default: 2248 log.warn("Unexpected column {} in setValueAt", c); 2249 break; 2250 } 2251 } 2252 } 2253 2254 /** 2255 * Table model for selecting output variables 2256 */ 2257 private class AlignmentModel extends RouteElementModel { 2258 2259 @Override 2260 public boolean isInput() { 2261 return false; 2262 } 2263 2264 @Override 2265 public String getColumnName(int c) { 2266 if (c == STATE_COLUMN) { 2267 return rbx.getString("Alignment"); 2268 } 2269 return super.getColumnName(c); 2270 } 2271 2272 @Override 2273 public int getRowCount() { 2274 if (_showAllAlign) { 2275 return _alignList.size(); 2276 } else { 2277 return _includedAlignList.size(); 2278 } 2279 } 2280 2281 @Override 2282 public Object getValueAt(int r, int c) { 2283 ArrayList<AlignElement> alignList; 2284 if (_showAllAlign) { 2285 alignList = _alignList; 2286 } else { 2287 alignList = _includedAlignList; 2288 } 2289 // some error checking 2290 if (r >= alignList.size()) { 2291 log.debug("row out of range"); 2292 return null; 2293 } 2294 switch (c) { 2295 case SNAME_COLUMN: // slot number 2296 return alignList.get(r).getSysName(); 2297 case UNAME_COLUMN: // 2298 return alignList.get(r).getUserName(); 2299 case INCLUDE_COLUMN: 2300 return alignList.get(r).isIncluded(); 2301 case TYPE_COLUMN: 2302 return Bundle.getMessage("BeanNameSensor"); 2303 case STATE_COLUMN: // 2304 return alignList.get(r).getAlignType(); 2305 default: 2306 return null; 2307 } 2308 } 2309 2310 @Override 2311 public void setValueAt(Object type, int r, int c) { 2312 ArrayList<AlignElement> alignList; 2313 if (_showAllAlign) { 2314 alignList = _alignList; 2315 } else { 2316 alignList = _includedAlignList; 2317 } 2318 switch (c) { 2319 case INCLUDE_COLUMN: 2320 alignList.get(r).setIncluded(((Boolean) type)); 2321 break; 2322 case STATE_COLUMN: 2323 alignList.get(r).setAlignType((String) type); 2324 break; 2325 default: 2326 log.warn("Unexpected column {} in setValueAt", c); 2327 break; 2328 } 2329 } 2330 } 2331 2332 public static final String CONDITIONAL_USER_PREFIX = "Route "; 2333 2334 public static final int SENSOR_TYPE = 1; 2335 public static final int TURNOUT_TYPE = 2; 2336 public static final int LIGHT_TYPE = 3; 2337 public static final int SIGNAL_TYPE = 4; 2338 public static final int CONDITIONAL_TYPE = 5; 2339 public static final int ALL_TYPE = 6; 2340 2341 // Should not conflict with state variable types 2342 public static final int VETO = 0x80; 2343 // due to the unecessary bit assignments in SignalHead for appearances, 2344 // offset the following 2345 public static final int OFFSET = 0x30; 2346 public static final int SET_SIGNAL_HELD = Conditional.ACTION_SET_SIGNAL_HELD + OFFSET; 2347 public static final int CLEAR_SIGNAL_HELD = Conditional.ACTION_CLEAR_SIGNAL_HELD + OFFSET; 2348 public static final int SET_SIGNAL_DARK = Conditional.ACTION_SET_SIGNAL_DARK + OFFSET; 2349 public static final int SET_SIGNAL_LIT = Conditional.ACTION_SET_SIGNAL_LIT + OFFSET; 2350 2351 private static final String ALIGN_SENSOR = rbx.getString("AlignSensor"); 2352 private static final String ALIGN_TURNOUT = rbx.getString("AlignTurnout"); 2353 private static final String ALIGN_LIGHT = rbx.getString("AlignLight"); 2354 private static final String ALIGN_SIGNAL = rbx.getString("AlignSignal"); 2355 private static final String ALIGN_ALL = rbx.getString("AlignAll"); 2356 2357 private static final String ON_CHANGE = Bundle.getMessage("OnConditionChange"); 2358 private static final String ON_ACTIVE = Bundle.getMessage("OnCondition") 2359 + " " + Bundle.getMessage("SensorStateActive"); 2360 private static final String ON_INACTIVE = Bundle.getMessage("OnCondition") 2361 + " " + Bundle.getMessage("SensorStateInactive"); 2362 private static final String VETO_ON_ACTIVE = "Veto " + Bundle.getMessage("WhenCondition") 2363 + " " + Bundle.getMessage("SensorStateActive"); 2364 private static final String VETO_ON_INACTIVE = "Veto " + Bundle.getMessage("WhenCondition") 2365 + " " + Bundle.getMessage("SensorStateInactive"); 2366 private static final String ON_THROWN = Bundle.getMessage("OnCondition") 2367 + " " + Bundle.getMessage("TurnoutStateThrown"); 2368 private static final String ON_CLOSED = Bundle.getMessage("OnCondition") 2369 + " " + Bundle.getMessage("TurnoutStateClosed"); 2370 private static final String VETO_ON_THROWN = "Veto " + Bundle.getMessage("WhenCondition") 2371 + " " + Bundle.getMessage("TurnoutStateThrown"); 2372 private static final String VETO_ON_CLOSED = "Veto " + Bundle.getMessage("WhenCondition") 2373 + " " + Bundle.getMessage("TurnoutStateClosed"); 2374 private static final String ON_LIT = Bundle.getMessage("OnCondition") 2375 + " " + Bundle.getMessage("ColumnHeadLit"); 2376 private static final String ON_UNLIT = rbx.getString("OnUnLit"); 2377 private static final String VETO_ON_LIT = "Veto " + Bundle.getMessage("WhenCondition") 2378 + " " + Bundle.getMessage("ColumnHeadLit"); 2379 private static final String VETO_ON_UNLIT = rbx.getString("VetoUnLit"); 2380 private static final String ON_RED = Bundle.getMessage("OnCondition") 2381 + " " + Bundle.getMessage("SignalHeadStateRed"); 2382 private static final String ON_FLASHRED = Bundle.getMessage("OnCondition") 2383 + " " + Bundle.getMessage("SignalHeadStateFlashingRed"); 2384 private static final String ON_YELLOW = Bundle.getMessage("OnCondition") 2385 + " " + Bundle.getMessage("SignalHeadStateYellow"); 2386 private static final String ON_FLASHYELLOW = Bundle.getMessage("OnCondition") 2387 + " " + Bundle.getMessage("SignalHeadStateFlashingYellow"); 2388 private static final String ON_GREEN = Bundle.getMessage("OnCondition") 2389 + " " + Bundle.getMessage("SignalHeadStateGreen"); 2390 private static final String ON_FLASHGREEN = Bundle.getMessage("OnCondition") 2391 + " " + Bundle.getMessage("SignalHeadStateFlashingGreen"); 2392 private static final String ON_DARK = Bundle.getMessage("OnCondition") 2393 + " " + Bundle.getMessage("SignalHeadStateDark"); 2394 private static final String ON_SIGNAL_LIT = Bundle.getMessage("OnCondition") 2395 + " " + Bundle.getMessage("ColumnHeadLit"); 2396 private static final String ON_SIGNAL_HELD = Bundle.getMessage("OnCondition") 2397 + " " + Bundle.getMessage("SignalHeadStateHeld"); 2398 private static final String VETO_ON_RED = "Veto " + Bundle.getMessage("WhenCondition") 2399 + " " + Bundle.getMessage("SignalHeadStateRed"); 2400 private static final String VETO_ON_FLASHRED = "Veto " + Bundle.getMessage("WhenCondition") 2401 + " " + Bundle.getMessage("SignalHeadStateFlashingRed"); 2402 private static final String VETO_ON_YELLOW = "Veto " + Bundle.getMessage("WhenCondition") 2403 + " " + Bundle.getMessage("SignalHeadStateYellow"); 2404 private static final String VETO_ON_FLASHYELLOW = "Veto " + Bundle.getMessage("WhenCondition") 2405 + " " + Bundle.getMessage("SignalHeadStateFlashingYellow"); 2406 private static final String VETO_ON_GREEN = "Veto " + Bundle.getMessage("WhenCondition") 2407 + " " + Bundle.getMessage("SignalHeadStateGreen"); 2408 private static final String VETO_ON_FLASHGREEN = "Veto " + Bundle.getMessage("WhenCondition") 2409 + " " + Bundle.getMessage("SignalHeadStateFlashingGreen"); 2410 private static final String VETO_ON_DARK = "Veto " + Bundle.getMessage("WhenCondition") 2411 + " " + Bundle.getMessage("SignalHeadStateDark"); 2412 private static final String VETO_ON_SIGNAL_LIT = "Veto " + Bundle.getMessage("WhenCondition") 2413 + " " + Bundle.getMessage("ColumnHeadLit"); 2414 private static final String VETO_ON_SIGNAL_HELD = "Veto " + Bundle.getMessage("WhenCondition") 2415 + " " + Bundle.getMessage("SignalHeadStateHeld"); 2416 2417 private static final String SET_TO_ACTIVE = Bundle.getMessage("SetBeanState", 2418 Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("SensorStateActive")); 2419 private static final String SET_TO_INACTIVE = Bundle.getMessage("SetBeanState", 2420 Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("SensorStateInactive")); 2421 private static final String SET_TO_CLOSED = Bundle.getMessage("SetBeanState", 2422 Bundle.getMessage("BeanNameTurnout"), Bundle.getMessage("TurnoutStateClosed")); 2423 private static final String SET_TO_THROWN = Bundle.getMessage("SetBeanState", 2424 Bundle.getMessage("BeanNameTurnout"), Bundle.getMessage("TurnoutStateThrown")); 2425 private static final String SET_TO_TOGGLE = Bundle.getMessage("SetBeanState", 2426 "", Bundle.getMessage("Toggle")); 2427 private static final String SET_TO_ON = Bundle.getMessage("SetBeanState", 2428 Bundle.getMessage("BeanNameLight"), Bundle.getMessage("StateOn")); 2429 private static final String SET_TO_OFF = Bundle.getMessage("SetBeanState", 2430 Bundle.getMessage("BeanNameLight"), Bundle.getMessage("StateOff")); 2431 private static final String SET_TO_DARK = Bundle.getMessage("SetBeanState", 2432 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateDark")); 2433 private static final String SET_TO_LIT = Bundle.getMessage("SetBeanState", 2434 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("ColumnHeadLit")); 2435 private static final String SET_TO_HELD = Bundle.getMessage("SetBeanState", 2436 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateHeld")); 2437 private static final String SET_TO_CLEAR = rbx.getString("SetClear"); 2438 private static final String SET_TO_RED = Bundle.getMessage("SetBeanState", 2439 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateRed")); 2440 private static final String SET_TO_FLASHRED = Bundle.getMessage("SetBeanState", 2441 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingRed")); 2442 private static final String SET_TO_YELLOW = Bundle.getMessage("SetBeanState", 2443 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateYellow")); 2444 private static final String SET_TO_FLASHYELLOW = Bundle.getMessage("SetBeanState", 2445 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingYellow")); 2446 private static final String SET_TO_GREEN = Bundle.getMessage("SetBeanState", 2447 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateGreen")); 2448 private static final String SET_TO_FLASHGREEN = Bundle.getMessage("SetBeanState", 2449 Bundle.getMessage("BeanNameSignalHead"), Bundle.getMessage("SignalHeadStateFlashingGreen")); 2450 2451 private static final String[] ALIGNMENT_STATES = { 2452 ALIGN_SENSOR, ALIGN_TURNOUT, ALIGN_LIGHT, ALIGN_SIGNAL, ALIGN_ALL}; 2453 private static final String[] INPUT_SENSOR_STATES = { 2454 ON_ACTIVE, ON_INACTIVE, ON_CHANGE, VETO_ON_ACTIVE, VETO_ON_INACTIVE}; 2455 private static final String[] INPUT_TURNOUT_STATES = { 2456 ON_THROWN, ON_CLOSED, ON_CHANGE, VETO_ON_THROWN, VETO_ON_CLOSED}; 2457 private static final String[] INPUT_LIGHT_STATES = { 2458 ON_LIT, ON_UNLIT, ON_CHANGE, VETO_ON_LIT, VETO_ON_UNLIT}; 2459 private static final String[] INPUT_SIGNAL_STATES = { 2460 ON_RED, ON_FLASHRED, ON_YELLOW, ON_FLASHYELLOW, ON_GREEN, 2461 ON_FLASHGREEN, ON_DARK, ON_SIGNAL_LIT, ON_SIGNAL_HELD, VETO_ON_RED, 2462 VETO_ON_FLASHRED, VETO_ON_YELLOW, VETO_ON_FLASHYELLOW, VETO_ON_GREEN, 2463 VETO_ON_FLASHGREEN, VETO_ON_DARK, VETO_ON_SIGNAL_LIT, VETO_ON_SIGNAL_HELD}; 2464 private static final String[] OUTPUT_SENSOR_STATES = {SET_TO_ACTIVE, SET_TO_INACTIVE, SET_TO_TOGGLE}; 2465 private static final String[] OUTPUT_TURNOUT_STATES = {SET_TO_CLOSED, SET_TO_THROWN, SET_TO_TOGGLE}; 2466 private static final String[] OUTPUT_LIGHT_STATES = {SET_TO_ON, SET_TO_OFF, SET_TO_TOGGLE}; 2467 private static final String[] OUTPUT_SIGNAL_STATES = {SET_TO_DARK, SET_TO_LIT, SET_TO_HELD, SET_TO_CLEAR, 2468 SET_TO_RED, SET_TO_FLASHRED, SET_TO_YELLOW, 2469 SET_TO_FLASHYELLOW, SET_TO_GREEN, SET_TO_FLASHGREEN}; 2470 2471 private static String getLogixSystemPrefix() { 2472 // Note: RouteExportToLogix uses ":RTX:" which is right? 2473 return InstanceManager.getDefault(LogixManager.class).getSystemNamePrefix() + ":RTX"; 2474 } 2475 2476 // should be private or package protected, but hey, its Logix! so its public 2477 // because Logix is scattered across all of JMRI without rhyme or reason 2478 public static String getLogixInitializer() { 2479 return getLogixSystemPrefix() + "INITIALIZER"; 2480 } 2481 2482 private String getConditionalSystemPrefix() { 2483 return getLogixSystemPrefix() + "C"; 2484 } 2485 2486 /** 2487 * Sorts RouteElement 2488 */ 2489 public static class RouteElementComparator implements java.util.Comparator<RouteElement> { 2490 // RouteElement objects aren't really NamedBeans, as they don't inherit 2491 // so we have to create our own comparator object here. This assumes they 2492 // the do have a named-bean-like system name format. 2493 RouteElementComparator() { 2494 } 2495 2496 private static final jmri.util.AlphanumComparator ac = new jmri.util.AlphanumComparator(); 2497 2498 @Override 2499 public int compare(RouteElement e1, RouteElement e2) { 2500 String s1 = e1.getSysName(); 2501 String s2 = e2.getSysName(); 2502 2503 int p1len = Manager.getSystemPrefixLength(s1); 2504 int p2len = Manager.getSystemPrefixLength(s2); 2505 2506 int comp = ac.compare(s1.substring(0, p1len), s2.substring(0, p2len)); 2507 if (comp != 0) { 2508 return comp; 2509 } 2510 2511 char c1 = s1.charAt(p1len); 2512 char c2 = s2.charAt(p2len); 2513 2514 if (c1 == c2) { 2515 return ac.compare(s1.substring(p1len+1), s2.substring(p2len+1)); 2516 } else { 2517 return (c1 > c2) ? +1 : -1 ; 2518 } 2519 } 2520 2521 } 2522 2523 /** 2524 * Base class for all the output (ConditionalAction) and input 2525 * (ConditionalVariable) elements 2526 */ 2527 static class RouteElement { 2528 2529 private String _sysName; 2530 private String _userName; 2531 private int _type; 2532 private String _typeString; 2533 private boolean _included; 2534 int _state; 2535 2536 RouteElement(String sysName, String userName, int type) { 2537 _sysName = sysName; 2538 _userName = userName; 2539 _type = type; 2540 _included = false; 2541 switch (type) { 2542 case SENSOR_TYPE: 2543 _typeString = Bundle.getMessage("BeanNameSensor"); 2544 break; 2545 case TURNOUT_TYPE: 2546 _typeString = Bundle.getMessage("BeanNameTurnout"); 2547 break; 2548 case LIGHT_TYPE: 2549 _typeString = Bundle.getMessage("BeanNameLight"); 2550 break; 2551 case SIGNAL_TYPE: 2552 _typeString = Bundle.getMessage("BeanNameSignalHead"); 2553 break; 2554 case CONDITIONAL_TYPE: 2555 _typeString = Bundle.getMessage("BeanNameConditional"); 2556 break; 2557 default: 2558 log.warn("Unexpected type {} in RouteElement constructor", type); 2559 break; 2560 } 2561 } 2562 2563 String getSysName() { 2564 return _sysName; 2565 } 2566 2567 String getUserName() { 2568 return _userName; 2569 } 2570 2571 int getType() { 2572 return _type; 2573 } 2574 2575 String getTypeString() { 2576 return _typeString; 2577 } 2578 2579 boolean isIncluded() { 2580 return _included; 2581 } 2582 2583 void setIncluded(boolean include) { 2584 _included = include; 2585 } 2586 2587 int getState() { 2588 return _state; 2589 } 2590 2591 final void setState(int state) { 2592 _state = state; 2593 } 2594 } 2595 2596 abstract class RouteInputElement extends RouteElement { 2597 2598 RouteInputElement(String sysName, String userName, int type) { 2599 super(sysName, userName, type); 2600 } 2601 2602 abstract String getTestState(); 2603 2604 abstract void setTestState(String state); 2605 } 2606 2607 private class RouteInputSensor extends RouteInputElement { 2608 2609 RouteInputSensor(String sysName, String userName) { 2610 super(sysName, userName, SENSOR_TYPE); 2611 setState(Conditional.TYPE_SENSOR_ACTIVE); 2612 } 2613 2614 @Override 2615 String getTestState() { 2616 switch (_state) { 2617 case Conditional.TYPE_SENSOR_INACTIVE: 2618 return ON_INACTIVE; 2619 case Conditional.TYPE_SENSOR_ACTIVE: 2620 return ON_ACTIVE; 2621 case Route.ONCHANGE: 2622 return ON_CHANGE; 2623 case VETO + Conditional.TYPE_SENSOR_INACTIVE: 2624 return VETO_ON_INACTIVE; 2625 case VETO + Conditional.TYPE_SENSOR_ACTIVE: 2626 return VETO_ON_ACTIVE; 2627 default: 2628 log.error("Unhandled test state type: {}", _state); 2629 break; 2630 } 2631 return ""; 2632 } 2633 2634 @Override 2635 void setTestState(String state) { 2636 if (ON_INACTIVE.equals(state)) { 2637 _state = Conditional.TYPE_SENSOR_INACTIVE; 2638 } else if (ON_ACTIVE.equals(state)) { 2639 _state = Conditional.TYPE_SENSOR_ACTIVE; 2640 } else if (ON_CHANGE.equals(state)) { 2641 _state = Route.ONCHANGE; 2642 } else if (VETO_ON_INACTIVE.equals(state)) { 2643 _state = VETO + Conditional.TYPE_SENSOR_INACTIVE; 2644 } else if (VETO_ON_ACTIVE.equals(state)) { 2645 _state = VETO + Conditional.TYPE_SENSOR_ACTIVE; 2646 } 2647 } 2648 } 2649 2650 private class RouteInputTurnout extends RouteInputElement { 2651 2652 RouteInputTurnout(String sysName, String userName) { 2653 super(sysName, userName, TURNOUT_TYPE); 2654 setState(Conditional.TYPE_TURNOUT_CLOSED); 2655 } 2656 2657 @Override 2658 String getTestState() { 2659 switch (_state) { 2660 case Conditional.TYPE_TURNOUT_CLOSED: 2661 return ON_CLOSED; 2662 case Conditional.TYPE_TURNOUT_THROWN: 2663 return ON_THROWN; 2664 case Route.ONCHANGE: 2665 return ON_CHANGE; 2666 case VETO + Conditional.TYPE_TURNOUT_CLOSED: 2667 return VETO_ON_CLOSED; 2668 case VETO + Conditional.TYPE_TURNOUT_THROWN: 2669 return VETO_ON_THROWN; 2670 default: 2671 log.warn("Unhandled test state type: {}", _state); 2672 } 2673 return ""; 2674 } 2675 2676 @Override 2677 void setTestState(String state) { 2678 if (ON_CLOSED.equals(state)) { 2679 _state = Conditional.TYPE_TURNOUT_CLOSED; 2680 } else if (ON_THROWN.equals(state)) { 2681 _state = Conditional.TYPE_TURNOUT_THROWN; 2682 } else if (ON_CHANGE.equals(state)) { 2683 _state = Route.ONCHANGE; 2684 } else if (VETO_ON_CLOSED.equals(state)) { 2685 _state = VETO + Conditional.TYPE_TURNOUT_CLOSED; 2686 } else if (VETO_ON_THROWN.equals(state)) { 2687 _state = VETO + Conditional.TYPE_TURNOUT_THROWN; 2688 } 2689 } 2690 } 2691 2692 private class RouteInputLight extends RouteInputElement { 2693 2694 RouteInputLight(String sysName, String userName) { 2695 super(sysName, userName, LIGHT_TYPE); 2696 setState(Conditional.TYPE_LIGHT_OFF); 2697 } 2698 2699 @Override 2700 String getTestState() { 2701 switch (_state) { 2702 case Conditional.TYPE_LIGHT_OFF: 2703 return ON_UNLIT; 2704 case Conditional.TYPE_LIGHT_ON: 2705 return ON_LIT; 2706 case Route.ONCHANGE: 2707 return ON_CHANGE; 2708 case VETO + Conditional.TYPE_LIGHT_OFF: 2709 return VETO_ON_UNLIT; 2710 case VETO + Conditional.TYPE_LIGHT_ON: 2711 return VETO_ON_LIT; 2712 default: 2713 log.warn("Unhandled test state: {}", _state); 2714 break; 2715 } 2716 return ""; 2717 } 2718 2719 @Override 2720 void setTestState(String state) { 2721 if (ON_UNLIT.equals(state)) { 2722 _state = Conditional.TYPE_LIGHT_OFF; 2723 } else if (ON_LIT.equals(state)) { 2724 _state = Conditional.TYPE_LIGHT_ON; 2725 } else if (ON_CHANGE.equals(state)) { 2726 _state = Route.ONCHANGE; 2727 } else if (VETO_ON_UNLIT.equals(state)) { 2728 _state = VETO + Conditional.TYPE_LIGHT_OFF; 2729 } else if (VETO_ON_LIT.equals(state)) { 2730 _state = VETO + Conditional.TYPE_LIGHT_ON; 2731 } 2732 } 2733 } 2734 2735 private class RouteInputSignal extends RouteInputElement { 2736 2737 RouteInputSignal(String sysName, String userName) { 2738 super(sysName, userName, SIGNAL_TYPE); 2739 setState(Conditional.TYPE_SIGNAL_HEAD_LIT); 2740 } 2741 2742 @Override 2743 String getTestState() { 2744 switch (_state) { 2745 case Conditional.TYPE_SIGNAL_HEAD_RED: 2746 return ON_RED; 2747 case Conditional.TYPE_SIGNAL_HEAD_FLASHRED: 2748 return ON_FLASHRED; 2749 case Conditional.TYPE_SIGNAL_HEAD_YELLOW: 2750 return ON_YELLOW; 2751 case Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW: 2752 return ON_FLASHYELLOW; 2753 case Conditional.TYPE_SIGNAL_HEAD_GREEN: 2754 return ON_GREEN; 2755 case Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN: 2756 return ON_FLASHGREEN; 2757 case Conditional.TYPE_SIGNAL_HEAD_DARK: 2758 return ON_DARK; 2759 case Conditional.TYPE_SIGNAL_HEAD_LIT: 2760 return ON_SIGNAL_LIT; 2761 case Conditional.TYPE_SIGNAL_HEAD_HELD: 2762 return ON_SIGNAL_HELD; 2763 case VETO + Conditional.TYPE_SIGNAL_HEAD_RED: 2764 return VETO_ON_RED; 2765 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHRED: 2766 return VETO_ON_FLASHRED; 2767 case VETO + Conditional.TYPE_SIGNAL_HEAD_YELLOW: 2768 return VETO_ON_YELLOW; 2769 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW: 2770 return VETO_ON_FLASHYELLOW; 2771 case VETO + Conditional.TYPE_SIGNAL_HEAD_GREEN: 2772 return VETO_ON_GREEN; 2773 case VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN: 2774 return VETO_ON_FLASHGREEN; 2775 case VETO + Conditional.TYPE_SIGNAL_HEAD_DARK: 2776 return VETO_ON_DARK; 2777 case VETO + Conditional.TYPE_SIGNAL_HEAD_LIT: 2778 return VETO_ON_SIGNAL_LIT; 2779 case VETO + Conditional.TYPE_SIGNAL_HEAD_HELD: 2780 return VETO_ON_SIGNAL_HELD; 2781 default: 2782 log.warn("Unhandled test state: {}", _state); 2783 break; 2784 } 2785 return ""; 2786 } 2787 2788 @Override 2789 void setTestState(String state) { 2790 if (ON_RED.equals(state)) { 2791 _state = Conditional.TYPE_SIGNAL_HEAD_RED; 2792 } else if (ON_FLASHRED.equals(state)) { 2793 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHRED; 2794 } else if (ON_YELLOW.equals(state)) { 2795 _state = Conditional.TYPE_SIGNAL_HEAD_YELLOW; 2796 } else if (ON_FLASHYELLOW.equals(state)) { 2797 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW; 2798 } else if (ON_GREEN.equals(state)) { 2799 _state = Conditional.TYPE_SIGNAL_HEAD_GREEN; 2800 } else if (ON_FLASHGREEN.equals(state)) { 2801 _state = Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN; 2802 } else if (ON_DARK.equals(state)) { 2803 _state = Conditional.TYPE_SIGNAL_HEAD_DARK; 2804 } else if (ON_SIGNAL_LIT.equals(state)) { 2805 _state = Conditional.TYPE_SIGNAL_HEAD_LIT; 2806 } else if (ON_SIGNAL_HELD.equals(state)) { 2807 _state = Conditional.TYPE_SIGNAL_HEAD_HELD; 2808 } else if (VETO_ON_RED.equals(state)) { 2809 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_RED; 2810 } else if (VETO_ON_FLASHRED.equals(state)) { 2811 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHRED; 2812 } else if (VETO_ON_YELLOW.equals(state)) { 2813 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_YELLOW; 2814 } else if (VETO_ON_FLASHYELLOW.equals(state)) { 2815 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHYELLOW; 2816 } else if (VETO_ON_GREEN.equals(state)) { 2817 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_GREEN; 2818 } else if (VETO_ON_FLASHGREEN.equals(state)) { 2819 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_FLASHGREEN; 2820 } else if (VETO_ON_DARK.equals(state)) { 2821 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_DARK; 2822 } else if (VETO_ON_SIGNAL_LIT.equals(state)) { 2823 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_LIT; 2824 } else if (VETO_ON_SIGNAL_HELD.equals(state)) { 2825 _state = VETO + Conditional.TYPE_SIGNAL_HEAD_HELD; 2826 } 2827 } 2828 } 2829 2830 abstract class RouteOutputElement extends RouteElement { 2831 2832 RouteOutputElement(String sysName, String userName, int type) { 2833 super(sysName, userName, type); 2834 } 2835 2836 abstract String getSetToState(); 2837 2838 abstract void setSetToState(String state); 2839 } 2840 2841 private class RouteOutputSensor extends RouteOutputElement { 2842 2843 RouteOutputSensor(String sysName, String userName) { 2844 super(sysName, userName, SENSOR_TYPE); 2845 setState(Sensor.ACTIVE); 2846 } 2847 2848 @Override 2849 String getSetToState() { 2850 switch (_state) { 2851 case Sensor.INACTIVE: 2852 return SET_TO_INACTIVE; 2853 case Sensor.ACTIVE: 2854 return SET_TO_ACTIVE; 2855 case Route.TOGGLE: 2856 return SET_TO_TOGGLE; 2857 default: 2858 log.warn("Unhandled set to state: {}", _state); 2859 break; 2860 } 2861 return ""; 2862 } 2863 2864 @Override 2865 void setSetToState(String state) { 2866 if (SET_TO_INACTIVE.equals(state)) { 2867 _state = Sensor.INACTIVE; 2868 } else if (SET_TO_ACTIVE.equals(state)) { 2869 _state = Sensor.ACTIVE; 2870 } else if (SET_TO_TOGGLE.equals(state)) { 2871 _state = Route.TOGGLE; 2872 } 2873 } 2874 } 2875 2876 private class RouteOutputTurnout extends RouteOutputElement { 2877 2878 RouteOutputTurnout(String sysName, String userName) { 2879 super(sysName, userName, TURNOUT_TYPE); 2880 setState(Turnout.CLOSED); 2881 } 2882 2883 @Override 2884 String getSetToState() { 2885 switch (_state) { 2886 case Turnout.CLOSED: 2887 return SET_TO_CLOSED; 2888 case Turnout.THROWN: 2889 return SET_TO_THROWN; 2890 case Route.TOGGLE: 2891 return SET_TO_TOGGLE; 2892 default: 2893 log.warn("Unhandled set to state: {}", _state); 2894 } 2895 return ""; 2896 } 2897 2898 @Override 2899 void setSetToState(String state) { 2900 if (SET_TO_CLOSED.equals(state)) { 2901 _state = Turnout.CLOSED; 2902 } else if (SET_TO_THROWN.equals(state)) { 2903 _state = Turnout.THROWN; 2904 } else if (SET_TO_TOGGLE.equals(state)) { 2905 _state = Route.TOGGLE; 2906 } 2907 } 2908 } 2909 2910 private class RouteOutputLight extends RouteOutputElement { 2911 2912 RouteOutputLight(String sysName, String userName) { 2913 super(sysName, userName, LIGHT_TYPE); 2914 setState(Light.ON); 2915 } 2916 2917 @Override 2918 String getSetToState() { 2919 switch (_state) { 2920 case Light.ON: 2921 return SET_TO_ON; 2922 case Light.OFF: 2923 return SET_TO_OFF; 2924 case Route.TOGGLE: 2925 return SET_TO_TOGGLE; 2926 default: 2927 log.warn("Unhandled set to state: {}", _state); 2928 } 2929 return ""; 2930 } 2931 2932 @Override 2933 void setSetToState(String state) { 2934 if (SET_TO_ON.equals(state)) { 2935 _state = Light.ON; 2936 } else if (SET_TO_OFF.equals(state)) { 2937 _state = Light.OFF; 2938 } else if (SET_TO_TOGGLE.equals(state)) { 2939 _state = Route.TOGGLE; 2940 } 2941 } 2942 } 2943 2944 private class RouteOutputSignal extends RouteOutputElement { 2945 2946 RouteOutputSignal(String sysName, String userName) { 2947 super(sysName, userName, SIGNAL_TYPE); 2948 setState(SignalHead.RED); 2949 } 2950 2951 @Override 2952 String getSetToState() { 2953 switch (_state) { 2954 case SignalHead.DARK: 2955 return SET_TO_DARK; 2956 case SignalHead.RED: 2957 return SET_TO_RED; 2958 case SignalHead.FLASHRED: 2959 return SET_TO_FLASHRED; 2960 case SignalHead.YELLOW: 2961 return SET_TO_YELLOW; 2962 case SignalHead.FLASHYELLOW: 2963 return SET_TO_FLASHYELLOW; 2964 case SignalHead.GREEN: 2965 return SET_TO_GREEN; 2966 case SignalHead.FLASHGREEN: 2967 return SET_TO_FLASHGREEN; 2968 case CLEAR_SIGNAL_HELD: 2969 return SET_TO_CLEAR; 2970 case SET_SIGNAL_LIT: 2971 return SET_TO_LIT; 2972 case SET_SIGNAL_HELD: 2973 return SET_TO_HELD; 2974 default: 2975 log.warn("Unhandled set to state: {}", _state); 2976 break; 2977 } 2978 return ""; 2979 } 2980 2981 @Override 2982 void setSetToState(String state) { 2983 if (SET_TO_DARK.equals(state)) { 2984 _state = SignalHead.DARK; 2985 } else if (SET_TO_RED.equals(state)) { 2986 _state = SignalHead.RED; 2987 } else if (SET_TO_FLASHRED.equals(state)) { 2988 _state = SignalHead.FLASHRED; 2989 } else if (SET_TO_YELLOW.equals(state)) { 2990 _state = SignalHead.YELLOW; 2991 } else if (SET_TO_FLASHYELLOW.equals(state)) { 2992 _state = SignalHead.FLASHYELLOW; 2993 } else if (SET_TO_GREEN.equals(state)) { 2994 _state = SignalHead.GREEN; 2995 } else if (SET_TO_FLASHGREEN.equals(state)) { 2996 _state = SignalHead.FLASHGREEN; 2997 } else if (SET_TO_CLEAR.equals(state)) { 2998 _state = CLEAR_SIGNAL_HELD; 2999 } else if (SET_TO_LIT.equals(state)) { 3000 _state = SET_SIGNAL_LIT; 3001 } else if (SET_TO_HELD.equals(state)) { 3002 _state = SET_SIGNAL_HELD; 3003 } 3004 } 3005 } 3006 3007 class AlignElement extends RouteElement { 3008 3009 AlignElement(String sysName, String userName) { 3010 super(sysName, userName, SENSOR_TYPE); 3011 setState(TURNOUT_TYPE); 3012 } 3013 3014 String getAlignType() { 3015 switch (_state) { 3016 case SENSOR_TYPE: 3017 return ALIGN_SENSOR; 3018 case TURNOUT_TYPE: 3019 return ALIGN_TURNOUT; 3020 case LIGHT_TYPE: 3021 return ALIGN_LIGHT; 3022 case SIGNAL_TYPE: 3023 return ALIGN_SIGNAL; 3024 case ALL_TYPE: 3025 return ALIGN_ALL; 3026 default: 3027 log.warn("Unhandled align type state: {}", _state); 3028 break; 3029 } 3030 return ""; 3031 } 3032 3033 void setAlignType(String state) { 3034 if (ALIGN_SENSOR.equals(state)) { 3035 _state = SENSOR_TYPE; 3036 } else if (ALIGN_TURNOUT.equals(state)) { 3037 _state = TURNOUT_TYPE; 3038 } else if (ALIGN_LIGHT.equals(state)) { 3039 _state = LIGHT_TYPE; 3040 } else if (ALIGN_SIGNAL.equals(state)) { 3041 _state = SIGNAL_TYPE; 3042 } else if (ALIGN_ALL.equals(state)) { 3043 _state = ALL_TYPE; 3044 } 3045 } 3046 } 3047 3048 @Override 3049 public void setMessagePreferencesDetails() { 3050 InstanceManager.getDefault(UserPreferencesManager.class).setPreferenceItemDetails( 3051 getClassName(), "remindSaveRoute", Bundle.getMessage("HideSaveReminder")); 3052 super.setMessagePreferencesDetails(); 3053 } 3054 3055 @Override 3056 protected String getClassName() { 3057 return LRouteTableAction.class.getName(); 3058 } 3059 3060 @Override 3061 public String getClassDescription() { 3062 return Bundle.getMessage("TitleLRouteTable"); 3063 } 3064 3065 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LRouteTableAction.class); 3066}