001package jmri.jmrit.beantable; 002 003import java.awt.BorderLayout; 004import java.awt.Component; 005import java.awt.Container; 006import java.awt.Dimension; 007import java.awt.FlowLayout; 008import java.awt.event.ActionEvent; 009import java.util.ArrayList; 010import java.util.Arrays; 011import java.util.List; 012import java.util.ResourceBundle; 013import java.util.Set; 014 015import javax.annotation.Nonnull; 016import javax.swing.*; 017import javax.swing.border.TitledBorder; 018import javax.swing.event.ChangeEvent; 019import javax.swing.table.DefaultTableCellRenderer; 020import javax.swing.table.TableCellEditor; 021import javax.swing.table.TableColumn; 022import javax.swing.table.TableColumnModel; 023 024import jmri.*; 025import jmri.NamedBean.DisplayOptions; 026import jmri.jmrit.dispatcher.TrainInfoFile; 027import jmri.jmrit.roster.RosterEntry; 028import jmri.jmrit.roster.swing.RosterEntryComboBox; 029import jmri.util.JmriJFrame; 030import jmri.swing.NamedBeanComboBox; 031import jmri.util.swing.JComboBoxUtil; 032import jmri.util.swing.JmriJOptionPane; 033import jmri.util.table.ButtonEditor; 034import jmri.util.table.ButtonRenderer; 035 036/** 037 * Swing action to create and register a TransitTable GUI. 038 * 039 * @author Dave Duchamp Copyright (C) 2008, 2010, 2011 040 */ 041public class TransitTableAction extends AbstractTableAction<Transit> { 042 043 /** 044 * Create an action with a specific title. 045 * <p> 046 * Note that the argument is the Action title, not the title of the 047 * resulting frame. Perhaps this should be changed? 048 * 049 * @param actionName action title 050 */ 051 public TransitTableAction(String actionName) { 052 super(actionName); 053 054 transitManager = InstanceManager.getNullableDefault(TransitManager.class); 055 // disable ourself if there is no Transit manager available 056 if (sectionManager == null || transitManager == null) { 057 super.setEnabled(false); 058 } 059 updateSensorList(); 060 } 061 062 public TransitTableAction() { 063 this(Bundle.getMessage("TitleTransitTable")); 064 } 065 066 static final ResourceBundle rbx = ResourceBundle.getBundle("jmri.jmrit.beantable.SectionTransitTableBundle"); 067 068 /** 069 * Create the JTable DataModel, along with the changes for the specific case 070 * of Transit objects. 071 */ 072 @Override 073 protected void createModel() { 074 m = new BeanTableDataModel<Transit>() { 075 076 static public final int EDITCOL = NUMCOLUMN; 077 static public final int DUPLICATECOL = EDITCOL + 1; 078 079 @Override 080 public String getValue(String name) { 081 if (name == null) { 082 log.warn("requested getValue(null)"); 083 return "(no name)"; 084 } 085 Transit z = InstanceManager.getDefault(TransitManager.class).getBySystemName(name); 086 if (z == null) { 087 log.debug("requested getValue(\"{}\"), Transit doesn't exist", name); 088 return "(no Transit)"; 089 } 090 return "Transit"; 091 } 092 093 @Override 094 public TransitManager getManager() { 095 return InstanceManager.getDefault(TransitManager.class); 096 } 097 098 @Override 099 public Transit getBySystemName(@Nonnull String name) { 100 return InstanceManager.getDefault(TransitManager.class).getBySystemName(name); 101 } 102 103 @Override 104 public Transit getByUserName(@Nonnull String name) { 105 return InstanceManager.getDefault(TransitManager.class).getByUserName(name); 106 } 107 108 @Override 109 protected String getMasterClassName() { 110 return getClassName(); 111 } 112 113 @Override 114 public void clickOn(Transit t) { 115 } 116 117 @Override 118 public int getColumnCount() { 119 return DUPLICATECOL + 1; 120 } 121 122 @Override 123 public Object getValueAt(int row, int col) { 124 switch (col) { 125 case VALUECOL: 126 // some error checking 127 if (row >= sysNameList.size()) { 128 log.debug("row is greater than name list"); 129 return ""; 130 } Transit z = getBySystemName(sysNameList.get(row)); 131 if (z == null) { 132 return ""; 133 } else { 134 int state = z.getState(); 135 if (state == Transit.IDLE) { 136 return (rbx.getString("TransitIdle")); 137 } else if (state == Transit.ASSIGNED) { 138 return (rbx.getString("TransitAssigned")); 139 } 140 } break; 141 case EDITCOL: 142 return Bundle.getMessage("ButtonEdit"); 143 case DUPLICATECOL: 144 return rbx.getString("ButtonDuplicate"); 145 default: 146 return super.getValueAt(row, col); 147 } 148 return null; 149 } 150 151 @Override 152 public void setValueAt(Object value, int row, int col) { 153 switch (col) { 154 case EDITCOL: 155 SwingUtilities.invokeLater(() -> { 156 editPressed(((Transit) getValueAt(row, SYSNAMECOL)).getSystemName()); 157 }); 158 break; 159 case DUPLICATECOL: 160 SwingUtilities.invokeLater(() -> { 161 duplicatePressed(((Transit) getValueAt(row, SYSNAMECOL)).getSystemName()); 162 }); 163 break; 164 default: 165 super.setValueAt(value, row, col); 166 break; 167 } 168 } 169 170 @Override 171 public String getColumnName(int col) { 172 switch (col) { 173 case EDITCOL: // no name on Edit column 174 case DUPLICATECOL: // no name on Duplicate column 175 return ""; 176 default: 177 return super.getColumnName(col); 178 } 179 } 180 181 @Override 182 public Class<?> getColumnClass(int col) { 183 switch (col) { 184 case VALUECOL: 185 return String.class; // not a button 186 case EDITCOL: 187 case DUPLICATECOL: 188 return JButton.class; 189 default: 190 return super.getColumnClass(col); 191 } 192 } 193 194 @Override 195 public boolean isCellEditable(int row, int col) { 196 switch (col) { 197 case VALUECOL: 198 return false; 199 case EDITCOL: 200 case DUPLICATECOL: 201 return true; 202 default: 203 return super.isCellEditable(row, col); 204 } 205 } 206 207 @Override 208 public int getPreferredWidth(int col) { 209 // override default value for SystemName and UserName columns 210 switch (col) { 211 case SYSNAMECOL: 212 return new JTextField(9).getPreferredSize().width; 213 case USERNAMECOL: 214 return new JTextField(17).getPreferredSize().width; 215 case VALUECOL: 216 case EDITCOL: 217 return new JTextField(6).getPreferredSize().width; 218 case DUPLICATECOL: 219 return new JTextField(10).getPreferredSize().width; 220 default: 221 return super.getPreferredWidth(col); 222 } 223 } 224 225 @Override 226 public void configValueColumn(JTable table) { 227 // value column isn't a button, so config is null 228 } 229 230 @Override 231 protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) { 232 return true; 233 // return (e.getPropertyName().indexOf("alue")=0); 234 } 235 236 @Override 237 public JButton configureButton() { 238 log.error("configureButton should not have been called"); 239 return null; 240 } 241 242 @Override 243 public void configureTable(JTable table) { 244 InstanceManager.getDefault(SensorManager.class).addPropertyChangeListener(this); 245 super.configureTable(table); 246 } 247 248 @Override 249 public void propertyChange(java.beans.PropertyChangeEvent e) { 250 if (e.getSource() instanceof SensorManager) { 251 if (e.getPropertyName().equals("DisplayListName") || e.getPropertyName().equals("length")) { 252 updateSensorList(); 253 } 254 } 255 super.propertyChange(e); 256 } 257 258 @Override 259 public void dispose(){ 260 InstanceManager.getDefault(SensorManager.class).removePropertyChangeListener(this); 261 super.dispose(); 262 } 263 264 }; 265 } 266 267 @Override 268 protected void setTitle() { 269 f.setTitle(Bundle.getMessage("TitleTransitTable")); 270 } 271 272 @Override 273 protected String helpTarget() { 274 return "package.jmri.jmrit.beantable.TransitTable"; 275 } 276 277 // instance variables 278 private boolean editMode = false; 279 private boolean duplicateMode = false; 280 private TransitManager transitManager = null; 281 private final SectionManager sectionManager = InstanceManager.getNullableDefault(SectionManager.class); 282 private Transit curTransit = null; 283 private SectionTableModel sectionTableModel = null; 284 private final List<Section> sectionList = new ArrayList<>(); 285 private final List<Integer> direction = new ArrayList<>(); 286 private final List<Integer> sequence = new ArrayList<>(); 287 private final List<List<TransitSectionAction>> action = new ArrayList<>(); 288 private final List<Boolean> alternate = new ArrayList<>(); 289 private final List<Boolean> safe = new ArrayList<>(); 290 private String[] sensorList; 291 private final List<String> sensorStopAllocation = new ArrayList<>(); 292 private final List<Float> fwdStopPerCent = new ArrayList<>(); 293 private final List<Float> revStopPerCent = new ArrayList<>(); 294 private final List<Section> primarySectionBoxList = new ArrayList<>(); 295 private final List<Integer> priSectionDirection = new ArrayList<>(); 296 private final List<Section> alternateSectionBoxList = new ArrayList<>(); 297 private final List<Integer> altSectionDirection = new ArrayList<>(); 298 private final List<Section> insertAtBeginningBoxList = new ArrayList<>(); 299 private final List<Integer> insertAtBeginningDirection = new ArrayList<>(); 300 private Section curSection = null; 301 private int curSectionDirection = 0; 302 private Section prevSection = null; 303 private int prevSectionDirection = 0; 304 private int curSequenceNum = 0; 305 306 // add/create variables 307 JmriJFrame addFrame = null; 308 JTextField sysName = new JTextField(15); 309 JLabel sysNameFixed = new JLabel(""); 310 JTextField userName = new JTextField(17); 311 JLabel sysNameLabel = new JLabel(Bundle.getMessage("LabelSystemName")); 312 JLabel userNameLabel = new JLabel(Bundle.getMessage("LabelUserName")); 313 JButton create = null; 314 JButton update = null; 315 JButton deleteSections = null; 316 JComboBox<String> primarySectionBox = new JComboBox<>(); 317 JButton addNextSection = null; 318 JCheckBox addAsSafe = null; 319 JComboBox<String> stopAllocatingSensorBox = new JComboBox<>(); 320 JButton removeLastSection = null; 321 JButton removeFirstSection = null; 322 JButton insertAtBeginning = null; 323 JComboBox<String> insertAtBeginningBox = new JComboBox<>(); 324 JLabel seqNumLabel = new JLabel(rbx.getString("LabelSeqNum")); 325 JSpinner seqNum = new JSpinner(new SpinnerNumberModel(1, 1, 1, 1)); 326 JButton replacePrimaryForSequence = null; 327 JButton deleteAlternateForSequence = null; 328 JButton addAlternateForSequence = null; 329 JComboBox<String> alternateSectionBox = new JComboBox<>(); 330 JButton addAlternateSection = null; 331 JCheckBox _autoSystemName = new JCheckBox(Bundle.getMessage("LabelAutoSysName")); 332 UserPreferencesManager pref; 333 String systemNameAuto = this.getClass().getName() + ".AutoSystemName"; 334 335 336 /** 337 * Responds to the Add...button and the Edit buttons in Transit Table. 338 * @param e Event causing method call. 339 */ 340 @Override 341 protected void addPressed(ActionEvent e) { 342 editMode = false; 343 duplicateMode = false; 344 if ((sectionManager.getNamedBeanSet().size()) > 0) { 345 addEditPressed(); 346 } else { 347 JmriJOptionPane.showMessageDialog(null, rbx 348 .getString("Message21"), Bundle.getMessage("ErrorTitle"), 349 JmriJOptionPane.ERROR_MESSAGE); 350 } 351 } 352 353 void editPressed(String sName) { 354 curTransit = transitManager.getBySystemName(sName); 355 if (curTransit == null) { 356 // no transit - should never happen, but protects against a $%^#@ exception 357 return; 358 } 359 sysNameFixed.setText(sName); 360 editMode = true; 361 duplicateMode = false; 362 addEditPressed(); 363 } 364 365 void duplicatePressed(String sName) { 366 curTransit = transitManager.getBySystemName(sName); 367 if (curTransit == null) { 368 // no transit - should never happen, but protects against a $%^#@ exception 369 return; 370 } 371 duplicateMode = true; 372 editMode = false; 373 addEditPressed(); 374 } 375 376 void addEditPressed() { 377 pref = InstanceManager.getDefault(UserPreferencesManager.class); 378 if (addFrame == null) { 379 addFrame = new JmriJFrame(Bundle.getMessage("TitleAddTransit")); 380 addFrame.addHelpMenu("package.jmri.jmrit.beantable.TransitAddEdit", true); 381 addFrame.getContentPane().setLayout(new BoxLayout(addFrame.getContentPane(), BoxLayout.Y_AXIS)); 382 JPanel p; 383 // system name 384 p = new JPanel(); 385 p.setLayout(new FlowLayout()); 386 p.add(sysNameLabel); 387 sysNameLabel.setLabelFor(sysName); 388 p.add(sysNameFixed); 389 p.add(sysName); 390 p.add(_autoSystemName); 391 _autoSystemName.addActionListener( e -> autoSystemName()); 392 if (pref.getSimplePreferenceState(systemNameAuto)) { 393 _autoSystemName.setSelected(true); 394 } 395 sysName.setToolTipText(rbx.getString("TransitSystemNameHint")); 396 addFrame.getContentPane().add(p); 397 // user name 398 p = new JPanel(); 399 p.add(userNameLabel); 400 userNameLabel.setLabelFor(userName); 401 p.add(userName); 402 userName.setToolTipText(rbx.getString("TransitUserNameHint")); 403 addFrame.getContentPane().add(p); 404 addFrame.getContentPane().add(new JSeparator()); 405 // instruction text fields 406 JPanel p1 = new JPanel(); 407 p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); 408 JPanel p11 = new JPanel(); 409 p11.setLayout(new FlowLayout()); 410 p11.add(new JLabel(rbx.getString("SectionTableMessage"))); 411 p1.add(p11); 412 JPanel p12 = new JPanel(); 413 p12.setLayout(new BorderLayout()); 414 // initialize table of sections 415 sectionTableModel = new SectionTableModel(); 416 JTable sectionTable = new JTable(sectionTableModel); 417 sectionTable.getTableHeader().setPreferredSize(new Dimension(0, new JLabel("<html>I<br>I</html>").getPreferredSize().height)); 418 sectionTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 419 sectionTable.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer()); 420 sectionTable.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor()); 421 sectionTable.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer()); 422 423 sectionTable.setRowSelectionAllowed(false); 424 TableColumnModel sectionColumnModel = sectionTable.getColumnModel(); 425 TableColumn sequenceColumn = sectionColumnModel.getColumn(SectionTableModel.SEQUENCE_COLUMN); 426 sequenceColumn.setResizable(true); 427 sequenceColumn.setMinWidth(50); 428 sequenceColumn.setMaxWidth(70); 429 TableColumn sectionColumn = sectionColumnModel.getColumn(SectionTableModel.SECTIONNAME_COLUMN); 430 sectionColumn.setResizable(true); 431 sectionColumn.setMinWidth(150); 432 TableColumn actionColumn = sectionColumnModel.getColumn(SectionTableModel.ACTION_COLUMN); 433 // install button renderer and editor 434 ButtonRenderer buttonRenderer = new ButtonRenderer(); 435 sectionTable.setDefaultRenderer(JButton.class, buttonRenderer); 436 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 437 sectionTable.setDefaultEditor(JButton.class, buttonEditor); 438 JButton testButton = new JButton(rbx.getString("AddEditActions")); 439 sectionTable.setRowHeight(testButton.getPreferredSize().height); 440 actionColumn.setResizable(false); 441 actionColumn.setMinWidth(testButton.getPreferredSize().width); 442 TableColumn directionColumn = sectionColumnModel.getColumn(SectionTableModel.SEC_DIRECTION_COLUMN); 443 directionColumn.setResizable(true); 444 String s = rbx.getString("DirectionColName"); 445 directionColumn.setMinWidth((int)new JLabel(s.substring(1, Math.min(s.length(), 7))).getPreferredSize().getWidth()); 446 directionColumn.setMaxWidth((int)new JLabel(rbx.getString("DirectionColName").concat("WW")).getPreferredSize().getWidth()); 447 TableColumn alternateColumn = sectionColumnModel.getColumn(SectionTableModel.ALTERNATE_COLUMN); 448 alternateColumn.setResizable(true); 449 s = rbx.getString("AlternateColName"); 450 alternateColumn.setMinWidth((int)new JLabel(s.substring(1, Math.min(s.length(), 7))).getPreferredSize().getWidth()); 451 alternateColumn.setMaxWidth((int)new JLabel(rbx.getString("AlternateColName").concat("WW")).getPreferredSize().getWidth()); 452 sectionColumnModel.getColumn(SectionTableModel.FWD_STOPPING_LENGTH).setCellEditor(new JSpinnerCellEditor()); 453 sectionColumnModel.getColumn(SectionTableModel.FWD_STOPPING_LENGTH).setCellRenderer(new JSpinnerCellRenderer()); 454 sectionColumnModel.getColumn(SectionTableModel.REV_STOPPING_LENGTH).setCellEditor(new JSpinnerCellEditor()); 455 sectionColumnModel.getColumn(SectionTableModel.REV_STOPPING_LENGTH).setCellRenderer(new JSpinnerCellRenderer()); 456 JScrollPane sectionTableScrollPane = new JScrollPane(sectionTable); 457 p12.add(sectionTableScrollPane, BorderLayout.CENTER); 458 p1.add(p12); 459 JPanel p13 = new JPanel(); 460 p13.add(primarySectionBox); 461 primarySectionBox.setToolTipText(rbx.getString("PrimarySectionBoxHint")); 462 p13.add(addNextSection = new JButton(rbx.getString("AddPrimaryButton"))); 463 p13.add(addAsSafe = new JCheckBox(Bundle.getMessage("TransitSectionIsSafe"))); 464 addAsSafe.setToolTipText(Bundle.getMessage("TransitSectionIsSafeHint")); 465 JPanel p13A = new JPanel(); 466 p13A.add(new JLabel(Bundle.getMessage("PauseAllocationOnSensorActive"))); 467 p13A.add(stopAllocatingSensorBox = new JComboBox<>(sensorList)); 468 JComboBoxUtil.setupComboBoxMaxRows(stopAllocatingSensorBox); 469 p13.add(p13A); 470 stopAllocatingSensorBox.setToolTipText(Bundle.getMessage("PauseAllocationOnSensorActiveHint")); 471 addNextSection.addActionListener(this::addNextSectionPressed); 472 addNextSection.setToolTipText(rbx.getString("AddPrimaryButtonHint")); 473 p13.setLayout(new FlowLayout()); 474 p1.add(p13); 475 JPanel p14 = new JPanel(); 476 p14.setLayout(new FlowLayout()); 477 p14.add(alternateSectionBox); 478 alternateSectionBox.setToolTipText(rbx.getString("AlternateSectionBoxHint")); 479 p14.add(addAlternateSection = new JButton(rbx.getString("AddAlternateButton"))); 480 addAlternateSection.addActionListener(this::addAlternateSectionPressed); 481 addAlternateSection.setToolTipText(rbx.getString("AddAlternateButtonHint")); 482 p14.add(new JLabel(" ")); // spacer between 2 groups of label + combobox 483 p14.add(insertAtBeginningBox); 484 insertAtBeginningBox.setToolTipText(rbx.getString("InsertAtBeginningBoxHint")); 485 p14.add(insertAtBeginning = new JButton(rbx.getString("InsertAtBeginningButton"))); 486 insertAtBeginning.addActionListener(this::insertAtBeginningPressed); 487 insertAtBeginning.setToolTipText(rbx.getString("InsertAtBeginningButtonHint")); 488 p1.add(p14); 489 p1.add(new JSeparator()); 490 JPanel p15 = new JPanel(); 491 p15.setLayout(new FlowLayout()); 492 p15.add(deleteSections = new JButton(rbx.getString("DeleteSectionsButton"))); 493 deleteSections.addActionListener(this::deleteAllSections); 494 deleteSections.setToolTipText(rbx.getString("DeleteSectionsButtonHint")); 495 p15.add(new JLabel(" ")); 496 p15.add(removeLastSection = new JButton(rbx.getString("RemoveLastButton"))); 497 removeLastSection.addActionListener(this::removeLastSectionPressed); 498 removeLastSection.setToolTipText(rbx.getString("RemoveLastButtonHint")); 499 p15.add(new JLabel(" ")); 500 p15.add(removeFirstSection = new JButton(rbx.getString("RemoveFirstButton"))); 501 removeFirstSection.addActionListener(this::removeFirstSectionPressed); 502 removeFirstSection.setToolTipText(rbx.getString("RemoveFirstButtonHint")); 503 p1.add(p15); 504 JPanel p16 = new JPanel(); 505 p16.setLayout(new FlowLayout()); 506 p16.add(seqNumLabel); 507 p16.add(seqNum); 508 seqNum.setToolTipText(rbx.getString("SeqNumHint")); 509 p1.add(p16); 510 JPanel p17 = new JPanel(); 511 p17.setLayout(new FlowLayout()); 512 p17.add(replacePrimaryForSequence = new JButton(rbx.getString("ReplacePrimaryForSeqButton"))); 513 replacePrimaryForSequence.addActionListener(this::replacePrimaryForSeqPressed); 514 replacePrimaryForSequence.setToolTipText(rbx.getString("ReplacePrimaryForSeqButtonHint")); 515 p17.add(new JLabel(" ")); 516 p17.add(deleteAlternateForSequence = new JButton(rbx.getString("DeleteAlternateForSeqButton"))); 517 deleteAlternateForSequence.addActionListener(this::deleteAlternateForSeqPressed); 518 deleteAlternateForSequence.setToolTipText(rbx.getString("DeleteAlternateForSeqButtonHint")); 519 p17.add(new JLabel(" ")); 520 p17.add(addAlternateForSequence = new JButton(rbx.getString("AddAlternateForSeqButton"))); 521 addAlternateForSequence.addActionListener(this::addAlternateForSeqPressed); 522 addAlternateForSequence.setToolTipText(rbx.getString("AddAlternateForSeqButtonHint")); 523 p1.add(p17); 524 addFrame.getContentPane().add(p1); 525 // set up bottom buttons 526 addFrame.getContentPane().add(new JSeparator()); 527 JButton cancel = new JButton(Bundle.getMessage("ButtonCancel")); // NOI18N 528 JPanel pb = new JPanel(); 529 pb.setLayout(new FlowLayout()); 530 pb.add(cancel ); 531 cancel.addActionListener(this::cancelPressed); 532 cancel.setToolTipText(rbx.getString("CancelButtonHint")); 533 pb.add(create = new JButton(Bundle.getMessage("ButtonCreate"))); 534 create.addActionListener(this::createPressed); 535 create.setToolTipText(rbx.getString("SectionCreateButtonHint")); 536 pb.add(update = new JButton(Bundle.getMessage("ButtonUpdate"))); 537 update.addActionListener(this::updatePressed); 538 update.setToolTipText(rbx.getString("SectionUpdateButtonHint")); 539 addFrame.getContentPane().add(pb); 540 } 541 if (editMode) { 542 // setup for edit window 543 addFrame.setTitle(Bundle.getMessage("TitleEditTransit")); 544 _autoSystemName.setVisible(false); 545 sysNameLabel.setEnabled(true); 546 create.setVisible(false); 547 update.setVisible(true); 548 sysName.setVisible(false); 549 sysNameFixed.setVisible(true); 550 addFrame.getRootPane().setDefaultButton(update); 551 initializeEditInformation(); 552 } else { 553 // setup for create window 554 addFrame.setTitle(Bundle.getMessage("TitleAddTransit")); 555 _autoSystemName.setVisible(true); 556 _autoSystemName.setEnabled(true); 557 autoSystemName(); 558 create.setVisible(true); 559 create.setEnabled(true); 560 update.setVisible(false); 561 sysName.setVisible(true); 562 sysNameFixed.setVisible(false); 563 addFrame.getRootPane().setDefaultButton(create); 564 if (duplicateMode) { 565 // setup with information from previous Transit 566 initializeEditInformation(); 567 sysName.setText(curTransit.getSystemName()); 568 curTransit = null; 569 } else { 570 deleteAllSections(null); 571 } 572 } 573 initializeSectionCombos(); 574 updateSeqNum(); 575 addFrame.setEscapeKeyClosesWindow(true); 576 addFrame.pack(); 577 addFrame.setVisible(true); 578 } 579 580 private void initializeEditInformation() { 581 sectionList.clear(); 582 sequence.clear(); 583 action.clear(); 584 direction.clear(); 585 alternate.clear(); 586 safe.clear(); 587 sensorStopAllocation.clear(); 588 fwdStopPerCent.clear(); 589 revStopPerCent.clear(); 590 591 curSection = null; 592 curSectionDirection = 0; 593 curSequenceNum = 0; 594 prevSection = null; 595 prevSectionDirection = 0; 596 if (curTransit != null) { 597 userName.setText(curTransit.getUserName()); 598 List<TransitSection> tsList = curTransit.getTransitSectionList(); 599 for (int i = 0; i < tsList.size(); i++) { 600 TransitSection ts = tsList.get(i); 601 if (ts != null) { 602 sectionList.add(ts.getSection()); 603 sequence.add(ts.getSequenceNumber()); 604 direction.add(ts.getDirection()); 605 action.add(ts.getTransitSectionActionList()); 606 alternate.add(ts.isAlternate()); 607 safe.add(ts.isSafe()); 608 sensorStopAllocation.add(ts.getStopAllocatingSensor()); 609 fwdStopPerCent.add(ts.getFwdStopPerCent()); 610 revStopPerCent.add(ts.getRevStopPerCent()); 611 } 612 } 613 int index = sectionList.size() - 1; 614 if (index >= alternate.size()) { 615 index = alternate.size() - 1; 616 } 617 while (alternate.get(index) && (index > 0)) { 618 index--; 619 } 620 if (index >= 0) { 621 curSection = sectionList.get(index); 622 curSequenceNum = sequence.get(index); 623 if (index > 0) { 624 curSectionDirection = direction.get(index); 625 } 626 index--; 627 while ((index >= 0) && alternate.get(index)) { 628 index--; 629 } 630 if (index >= 0) { 631 prevSection = sectionList.get(index); 632 prevSectionDirection = direction.get(index); 633 } 634 } 635 } 636 sectionTableModel.fireTableDataChanged(); 637 } 638 639 private void deleteAllSections(ActionEvent e) { 640 sectionList.clear(); 641 direction.clear(); 642 sequence.clear(); 643 action.clear(); 644 alternate.clear(); 645 safe.clear(); 646 sensorStopAllocation.clear(); 647 fwdStopPerCent.clear(); 648 revStopPerCent.clear(); 649 curSection = null; 650 curSectionDirection = 0; 651 prevSection = null; 652 prevSectionDirection = 0; 653 curSequenceNum = 0; 654 initializeSectionCombos(); 655 updateSeqNum(); 656 sectionTableModel.fireTableDataChanged(); 657 } 658 659 void addNextSectionPressed(ActionEvent e) { 660 if (primarySectionBoxList.isEmpty()) { 661 JmriJOptionPane.showMessageDialog(addFrame, rbx 662 .getString("Message25"), Bundle.getMessage("ErrorTitle"), 663 JmriJOptionPane.ERROR_MESSAGE); 664 return; 665 } 666 int index = primarySectionBox.getSelectedIndex(); 667 Section s = primarySectionBoxList.get(index); 668 if (s != null) { 669 int j = sectionList.size(); 670 sectionList.add(s); 671 direction.add(priSectionDirection.get(index)); 672 curSequenceNum++; 673 sequence.add(curSequenceNum); 674 safe.add(addAsSafe.isSelected()); 675 if (stopAllocatingSensorBox.getSelectedIndex() >= 0) { 676 sensorStopAllocation.add((String)stopAllocatingSensorBox.getSelectedItem()); 677 } else { 678 sensorStopAllocation.add(""); 679 } 680 action.add(new ArrayList<>()); 681 alternate.add(false); 682 if ((sectionList.size() == 2) && (curSection != null)) { 683 if (forwardConnected(curSection, s, 0)) { 684 direction.set(0, Section.REVERSE); 685 } 686 curSectionDirection = direction.get(0); 687 } 688 prevSection = curSection; 689 prevSectionDirection = curSectionDirection; 690 curSection = s; 691 if (prevSection != null) { 692 curSectionDirection = direction.get(j); 693 } 694 initializeSectionCombos(); 695 } 696 updateSeqNum(); 697 sectionTableModel.fireTableDataChanged(); 698 } 699 700 void removeLastSectionPressed(ActionEvent e) { 701 if (sectionList.size() <= 1) { 702 deleteAllSections(e); 703 } else { 704 int j = sectionList.size() - 1; 705 if (!alternate.get(j)) { 706 curSequenceNum--; 707 curSection = sectionList.get(j - 1); 708 curSectionDirection = direction.get(j - 1); 709 // delete alternate if present 710 int k = j - 2; 711 while ((k >= 0) && alternate.get(k)) { 712 k--; 713 } 714 // After this delete we need the new previous section, if there is one. 715 if (k < 0) { 716 // There is no previous section 717 prevSection = null; 718 } else { 719 prevSection = sectionList.get(k); 720 prevSectionDirection = direction.get(k); 721 } 722 } 723 removeSupportingArrayEntries(j); 724 initializeSectionCombos(); 725 } 726 updateSeqNum(); 727 sectionTableModel.fireTableDataChanged(); 728 } 729 730 void insertAtBeginningPressed(ActionEvent e) { 731 if (insertAtBeginningBoxList.isEmpty()) { 732 JmriJOptionPane.showMessageDialog(addFrame, rbx 733 .getString("Message35"), Bundle.getMessage("ErrorTitle"), 734 JmriJOptionPane.ERROR_MESSAGE); 735 return; 736 } 737 int index = insertAtBeginningBox.getSelectedIndex(); 738 Section s = insertAtBeginningBoxList.get(index); 739 if (s != null) { 740 sectionList.add(0, s); 741 direction.add(0, insertAtBeginningDirection.get(index)); 742 curSequenceNum++; 743 sequence.add(0, 1); 744 alternate.add(0, false); 745 safe.add(0, addAsSafe.isSelected()); 746 sensorStopAllocation.add(0, ""); 747 action.add(0, new ArrayList<>()); 748 fwdStopPerCent.add(0, Float.valueOf(0.0f)); 749 if (curSequenceNum == 2) { 750 prevSectionDirection = direction.get(0); 751 prevSection = s; 752 } 753 initializeSectionCombos(); 754 } 755 updateSeqNum(); 756 sectionTableModel.fireTableDataChanged(); 757 } 758 759 void removeFirstSectionPressed(ActionEvent e) { 760 if (curSequenceNum <= 1) { 761 deleteAllSections(e); 762 } else { 763 // For alternates we delete all 764 int keep = 1; 765 while (alternate.get(keep)) { 766 keep++; 767 } 768 for (int c = 0; c < keep ; c++) { 769 removeSupportingArrayEntries(0); 770 curSequenceNum--; 771 } 772 initializeSectionCombos(); 773 } 774 updateSeqNum(); 775 sectionTableModel.fireTableDataChanged(); 776 } 777 778 void replacePrimaryForSeqPressed(ActionEvent e) { 779 int seq = getSeqNum(); 780 if (seq == 0) { 781 return; 782 } 783 Section sOld = null; 784 List<Section> altOldList = new ArrayList<>(); 785 Section beforeSection = null; 786 int beforeSectionDirection = 0; 787 Section afterSection = null; 788 int afterSectionDirection = 0; 789 int index = -1; 790 for (int i = 0; i < sectionList.size(); i++) { 791 if ((sequence.get(i) == seq) && (!alternate.get(i))) { 792 sOld = sectionList.get(i); 793 index = i; 794 } 795 if ((sequence.get(i) == seq) && alternate.get(i)) { 796 altOldList.add(sectionList.get(i)); 797 } 798 if ((sequence.get(i) == (seq - 1)) && (!alternate.get(i))) { 799 beforeSection = sectionList.get(i); 800 beforeSectionDirection = direction.get(i); 801 } 802 if ((sequence.get(i) == (seq + 1)) && (!alternate.get(i))) { 803 afterSection = sectionList.get(i); 804 afterSectionDirection = Section.FORWARD; 805 if (afterSectionDirection == direction.get(i)) { 806 afterSectionDirection = Section.REVERSE; 807 } 808 } 809 } 810 if (sOld == null) { 811 log.error("Missing primary Section for seq = {}", seq); 812 return; 813 } 814 List<Section> possibles = new ArrayList<>(); 815 List<Integer> possiblesDirection = new ArrayList<>(); 816 List<String> possibleNames = new ArrayList<>(); 817 818 for (Section s : sectionManager.getNamedBeanSet()) { 819 Section mayBeSection = null; 820 String mayBeName = s.getDisplayName(); 821 int mayBeDirection = 0; 822 if ((s != sOld) && (s != beforeSection) 823 && (s != afterSection) && (!inSectionList(s, altOldList))) { 824 if (beforeSection != null) { 825 if (forwardConnected(s, beforeSection, beforeSectionDirection)) { 826 mayBeSection = s; 827 mayBeDirection = Section.FORWARD; 828 } else if (reverseConnected(s, beforeSection, beforeSectionDirection)) { 829 mayBeSection = s; 830 mayBeDirection = Section.REVERSE; 831 } 832 if ((mayBeSection != null) && (afterSection != null)) { 833 if (mayBeDirection == Section.REVERSE) { 834 if (!forwardConnected(s, afterSection, afterSectionDirection)) { 835 mayBeSection = null; 836 } 837 } else { 838 if (!reverseConnected(s, afterSection, afterSectionDirection)) { 839 mayBeSection = null; 840 } 841 } 842 } 843 } else if (afterSection != null) { 844 if (forwardConnected(s, afterSection, afterSectionDirection)) { 845 mayBeSection = s; 846 mayBeDirection = Section.REVERSE; 847 } else if (reverseConnected(s, afterSection, afterSectionDirection)) { 848 mayBeSection = s; 849 mayBeDirection = Section.FORWARD; 850 } 851 } else { 852 mayBeSection = s; 853 mayBeDirection = Section.FORWARD; 854 } 855 if (mayBeSection != null) { 856 possibles.add(mayBeSection); 857 possiblesDirection.add(mayBeDirection); 858 possibleNames.add(mayBeName); 859 } 860 } 861 } 862 if (possibles.isEmpty()) { 863 JmriJOptionPane.showMessageDialog(addFrame, 864 java.text.MessageFormat.format(rbx.getString("Message36"), 865 new Object[]{"" + seq}), Bundle.getMessage("ErrorTitle"), 866 JmriJOptionPane.ERROR_MESSAGE); 867 return; 868 } 869 int k = 0; 870 if (possibles.size() > 1) { 871 Object choices[] = new Object[possibles.size()]; 872 for (int j = 0; j < possibles.size(); j++) { 873 choices[j] = possibleNames.get(j); 874 } 875 Object selName = JmriJOptionPane.showInputDialog(addFrame, 876 rbx.getString("ReplacePrimaryChoice"), 877 rbx.getString("ReplacePrimaryTitle"), 878 JmriJOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 879 if (selName == null) { 880 return; 881 } 882 for (int j = 0; j < possibles.size(); j++) { 883 if (selName.equals(choices[j])) { 884 k = j; 885 } 886 } 887 } 888 sectionList.remove(index); 889 sectionList.add(index, possibles.get(k)); 890 direction.set(index, possiblesDirection.get(k)); 891 if (index == (sectionList.size() - 1)) { 892 curSection = sectionList.get(index); 893 curSectionDirection = direction.get(index); 894 } else if (index == (sectionList.size() - 2)) { 895 prevSection = sectionList.get(index); 896 prevSectionDirection = direction.get(index); 897 } 898 initializeSectionCombos(); 899 sectionTableModel.fireTableDataChanged(); 900 } 901 902 boolean inSectionList(Section s, List<Section> sList) { 903 for (int i = 0; i < sList.size(); i++) { 904 if (sList.get(i) == s) { 905 return true; 906 } 907 } 908 return false; 909 } 910 911 private int getSeqNum() { 912 int n = (Integer) seqNum.getValue(); // JSpinner int from 1 - sectionList.size() 913 if (n > curSequenceNum) { 914 JmriJOptionPane.showMessageDialog(null, rbx 915 .getString("Message34"), Bundle.getMessage("ErrorTitle"), 916 JmriJOptionPane.ERROR_MESSAGE); 917 return 0; 918 } 919 return n; 920 } 921 922 /** 923 * After any add, delete etc the section sequence numbers need to be 924 * rebuilt. 925 * After which we update sequence Number spinner on pane. 926 * Limit spinner to highest sequence index in 927 * section table (column 0). 928 */ 929 void updateSeqNum() { 930 int seqMax = 0; 931 int seqNumber = 0; 932 for (int ix = 0; ix<alternate.size();ix++) { 933 if (!alternate.get(ix)) { 934 seqNumber++; 935 } 936 sequence.set(ix,seqNumber); 937 } 938 seqMax = seqNumber; 939 seqNum.setModel(new SpinnerNumberModel( 940 seqMax, // initial value set 941 Math.min(seqMax, 1), // minimum value, either 0 (empty list) or 1 942 seqMax, // maximum order number 943 1)); 944 seqNum.setValue(Math.min(seqMax, 1)); 945 } 946 947 void deleteAlternateForSeqPressed(ActionEvent e) { 948 if (sectionList.size() <= 1) { 949 deleteAllSections(e); 950 } else { 951 int seq = getSeqNum(); 952 if (seq == 0) { 953 return; 954 } 955 for (int i = sectionList.size() - 1; i >= seq; i--) { 956 if ((sequence.get(i) == seq) && alternate.get(i)) { 957 removeSupportingArrayEntries(i); 958 } 959 } 960 initializeSectionCombos(); 961 } 962 updateSeqNum(); 963 sectionTableModel.fireTableDataChanged(); 964 } 965 966 void addAlternateForSeqPressed(ActionEvent e) { 967 int seq = getSeqNum(); 968 if (seq == 0) { 969 return; 970 } 971 Section primarySection = null; 972 List<Section> altOldList = new ArrayList<>(); 973 Section beforeSection = null; 974 int beforeSectionDirection = 0; 975 Section afterSection = null; 976 int afterSectionDirection = 0; 977 int index = -1; 978 for (int i = 0; i < sectionList.size(); i++) { 979 if ((sequence.get(i) == seq) && (!alternate.get(i))) { 980 primarySection = sectionList.get(i); 981 index = i; 982 } 983 if ((sequence.get(i) == seq) && alternate.get(i)) { 984 altOldList.add(sectionList.get(i)); 985 } 986 if ((sequence.get(i) == (seq - 1)) && (!alternate.get(i))) { 987 beforeSection = sectionList.get(i); 988 beforeSectionDirection = direction.get(i); 989 } 990 if ((sequence.get(i) == (seq + 1)) && (!alternate.get(i))) { 991 afterSection = sectionList.get(i); 992 afterSectionDirection = Section.FORWARD; 993 if (afterSectionDirection == direction.get(i)) { 994 afterSectionDirection = Section.REVERSE; 995 } 996 } 997 } 998 if (primarySection == null) { 999 log.error("Missing primary Section for seq = {}", seq); 1000 return; 1001 } 1002 List<Section> possibles = new ArrayList<>(); 1003 List<Integer> possiblesDirection = new ArrayList<>(); 1004 List<String> possibleNames = new ArrayList<>(); 1005 for (Section s : sectionManager.getNamedBeanSet()) { 1006 Section mayBeSection = null; 1007 String mayBeName = s.getDisplayName(); 1008 int mayBeDirection = 0; 1009 if ((s != primarySection) && (s != beforeSection) 1010 && (s != afterSection) && (!inSectionList(s, altOldList))) { 1011 if (beforeSection != null) { 1012 if (forwardConnected(s, beforeSection, beforeSectionDirection)) { 1013 mayBeSection = s; 1014 mayBeDirection = Section.FORWARD; 1015 } else if (reverseConnected(s, beforeSection, beforeSectionDirection)) { 1016 mayBeSection = s; 1017 mayBeDirection = Section.REVERSE; 1018 } 1019 if ((mayBeSection != null) && (afterSection != null)) { 1020 if (mayBeDirection == Section.REVERSE) { 1021 if (!forwardConnected(s, afterSection, afterSectionDirection)) { 1022 mayBeSection = null; 1023 } 1024 } else { 1025 if (!reverseConnected(s, afterSection, afterSectionDirection)) { 1026 mayBeSection = null; 1027 } 1028 } 1029 } 1030 } else if (afterSection != null) { 1031 if (forwardConnected(s, afterSection, afterSectionDirection)) { 1032 mayBeSection = s; 1033 mayBeDirection = Section.REVERSE; 1034 } else if (reverseConnected(s, afterSection, afterSectionDirection)) { 1035 mayBeSection = s; 1036 mayBeDirection = Section.FORWARD; 1037 } 1038 } else { 1039 mayBeSection = s; 1040 mayBeDirection = Section.FORWARD; 1041 } 1042 if (mayBeSection != null) { 1043 possibles.add(mayBeSection); 1044 possiblesDirection.add(mayBeDirection); 1045 possibleNames.add(mayBeName); 1046 } 1047 } 1048 } 1049 if (possibles.isEmpty()) { 1050 JmriJOptionPane.showMessageDialog(addFrame, 1051 java.text.MessageFormat.format(rbx.getString("Message37"), 1052 new Object[]{"" + seq}), Bundle.getMessage("ErrorTitle"), 1053 JmriJOptionPane.ERROR_MESSAGE); 1054 return; 1055 } 1056 int k = 0; 1057 if (possibles.size() > 1) { 1058 Object choices[] = new Object[possibles.size()]; 1059 for (int j = 0; j < possibles.size(); j++) { 1060 choices[j] = possibleNames.get(j); 1061 } 1062 Object selName = JmriJOptionPane.showInputDialog(addFrame, 1063 rbx.getString("AddAlternateChoice"), 1064 rbx.getString("AddAlternateTitle"), 1065 JmriJOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 1066 if (selName == null) { 1067 return; 1068 } 1069 for (int j = 0; j < possibles.size(); j++) { 1070 if (selName.equals(choices[j])) { 1071 k = j; 1072 } 1073 } 1074 } 1075 index = index + 1 + altOldList.size(); 1076 sectionList.add(index, possibles.get(k)); 1077 direction.add(index, possiblesDirection.get(k)); 1078 sequence.add(index, sequence.get(index - 1)); 1079 alternate.add(index, true); 1080 safe.add(index, addAsSafe.isSelected()); 1081 if (stopAllocatingSensorBox.getSelectedIndex() < 0) { 1082 sensorStopAllocation.add(index, ""); 1083 } else { 1084 sensorStopAllocation.add(index, (String) stopAllocatingSensorBox.getSelectedItem()); 1085 } 1086 if (stopAllocatingSensorBox.getSelectedIndex() < 0) { 1087 sensorStopAllocation.add(index, ""); 1088 } else { 1089 sensorStopAllocation.add(index, (String) stopAllocatingSensorBox.getSelectedItem()); 1090 } 1091 action.add(index, new ArrayList<>()); 1092 initializeSectionCombos(); 1093 updateSeqNum(); 1094 sectionTableModel.fireTableDataChanged(); 1095 } 1096 1097 void addAlternateSectionPressed(ActionEvent e) { 1098 if (alternateSectionBoxList.isEmpty()) { 1099 JmriJOptionPane.showMessageDialog(addFrame, rbx 1100 .getString("Message24"), Bundle.getMessage("ErrorTitle"), 1101 JmriJOptionPane.ERROR_MESSAGE); 1102 return; 1103 } 1104 int index = alternateSectionBox.getSelectedIndex(); 1105 Section s = alternateSectionBoxList.get(index); 1106 if (s != null) { 1107 sectionList.add(s); 1108 direction.add(altSectionDirection.get(index)); 1109 sequence.add(curSequenceNum); 1110 action.add(new ArrayList<>()); 1111 alternate.add(true); 1112 safe.add(addAsSafe.isSelected()); 1113 sensorStopAllocation.add((String)stopAllocatingSensorBox.getSelectedItem()); 1114 initializeSectionCombos(); 1115 } 1116 updateSeqNum(); 1117 sectionTableModel.fireTableDataChanged(); 1118 } 1119 1120 void createPressed(ActionEvent e) { 1121 if (!checkTransitInformation()) { 1122 return; 1123 } 1124 String uName = userName.getText(); 1125 if (uName.isEmpty()) { 1126 uName = null; 1127 } 1128 1129 try { 1130 // attempt to create the new Transit 1131 if (_autoSystemName.isSelected()) { 1132 curTransit = transitManager.createNewTransit(uName); 1133 } else { 1134 String sName = sysName.getText(); 1135 curTransit = transitManager.createNewTransit(sName, uName); 1136 } 1137 } catch (IllegalArgumentException ex) { 1138 JmriJOptionPane.showMessageDialog(addFrame, ex.getLocalizedMessage(), Bundle.getMessage("ErrorTitle"), 1139 JmriJOptionPane.ERROR_MESSAGE); 1140 return; 1141 } 1142 sysName.setText(curTransit.getSystemName()); 1143 setTransitInformation(); 1144 addFrame.setVisible(false); 1145 pref.setSimplePreferenceState(systemNameAuto, _autoSystemName.isSelected()); 1146 } 1147 1148 void cancelPressed(ActionEvent e) { 1149 addFrame.setVisible(false); 1150 sectionTableModel.dispose(); 1151 addFrame.dispose(); // remove addFrame from Windows menu 1152 addFrame = null; 1153 } 1154 1155 void updatePressed(ActionEvent e) { 1156 if (!checkTransitInformation()) { 1157 return; 1158 } 1159 // check if user name has been changed 1160 String uName = userName.getText(); 1161 if (uName.isEmpty()) { 1162 uName = null; 1163 } 1164 if ((uName != null) && (!uName.equals(curTransit.getUserName()))) { 1165 // check that new user name is unique 1166 Transit tTransit = transitManager.getByUserName(uName); 1167 if (tTransit != null) { 1168 JmriJOptionPane.showMessageDialog(addFrame, rbx 1169 .getString("Message22"), Bundle.getMessage("ErrorTitle"), 1170 JmriJOptionPane.ERROR_MESSAGE); 1171 return; 1172 } 1173 } 1174 curTransit.setUserName(uName); 1175 if (setTransitInformation()) { 1176 // successful update 1177 addFrame.setVisible(false); 1178 sectionTableModel.dispose(); 1179 addFrame.dispose(); // remove addFrame from Windows menu 1180 addFrame = null; 1181 } 1182 } 1183 1184 private void removeSupportingArrayEntries(int index) { 1185 sectionList.remove(index); 1186 sequence.remove(index); 1187 direction.remove(index); 1188 action.remove(index); 1189 alternate.remove(index); 1190 safe.remove(index); 1191 sensorStopAllocation.remove(index); 1192 fwdStopPerCent.remove(index); 1193 revStopPerCent.remove(index); 1194 } 1195 1196 private boolean checkTransitInformation() { 1197 //transits can now be of length 1 segmant. 1198 //With these the route has to start outside the transit 1199 /* 1200 if ((sectionList.size() <= 1) || (curSequenceNum <= 1)) { 1201 JmriJOptionPane.showMessageDialog(addFrame, rbx 1202 .getString("Message26"), Bundle.getMessage("ErrorTitle"), 1203 JmriJOptionPane.ERROR_MESSAGE); 1204 return false; 1205 } */ 1206 1207 return true; 1208 } 1209 1210 private boolean setTransitInformation() { 1211 if (curTransit == null) { 1212 return false; 1213 } 1214 curTransit.removeAllSections(); 1215 for (int i = 0; i < sectionList.size(); i++) { 1216 TransitSection ts = new TransitSection(sectionList.get(i), 1217 sequence.get(i), direction.get(i), alternate.get(i), safe.get(i), 1218 sensorStopAllocation.get(i), fwdStopPerCent.get(i), revStopPerCent.get(i)); 1219 List<TransitSectionAction> list = action.get(i); 1220 if (list != null) { 1221 for (int j = 0; j < list.size(); j++) { 1222 ts.addAction(list.get(j)); 1223 } 1224 } 1225 curTransit.addTransitSection(ts); 1226 } 1227 return true; 1228 } 1229 1230 private void initializeSectionCombos() { 1231 primarySectionBox.removeAllItems(); 1232 alternateSectionBox.removeAllItems(); 1233 insertAtBeginningBox.removeAllItems(); 1234 primarySectionBoxList.clear(); 1235 alternateSectionBoxList.clear(); 1236 insertAtBeginningBoxList.clear(); 1237 priSectionDirection.clear(); 1238 altSectionDirection.clear(); 1239 insertAtBeginningDirection.clear(); 1240 if (sectionList.isEmpty()) { 1241 // no Sections currently in Transit - all Sections and all Directions OK 1242 for (Section s : sectionManager.getNamedBeanSet()) { 1243 String sName = s.getDisplayName(); 1244 primarySectionBox.addItem(sName); 1245 primarySectionBoxList.add(s); 1246 priSectionDirection.add(Section.FORWARD); 1247 } 1248 } else { 1249 // limit to Sections that connect to the current Section and are not the previous Section 1250 for (Section s : sectionManager.getNamedBeanSet()) { 1251 String sName = s.getDisplayName(); 1252 if ((s != prevSection) && (forwardConnected(s, curSection, curSectionDirection))) { 1253 primarySectionBox.addItem(sName); 1254 primarySectionBoxList.add(s); 1255 priSectionDirection.add(Section.FORWARD); 1256 } else if ((s != prevSection) && (reverseConnected(s, curSection, curSectionDirection))) { 1257 primarySectionBox.addItem(sName); 1258 primarySectionBoxList.add(s); 1259 priSectionDirection.add(Section.REVERSE); 1260 } 1261 } 1262 // check if there are any alternate Section choices 1263 if (prevSection != null) { 1264 for (Section s : sectionManager.getNamedBeanSet()) { 1265 String sName = s.getDisplayName(); 1266 if ((notIncludedWithSeq(s, curSequenceNum)) 1267 && forwardConnected(s, prevSection, prevSectionDirection)) { 1268 alternateSectionBox.addItem(sName); 1269 alternateSectionBoxList.add(s); 1270 altSectionDirection.add( Section.FORWARD); 1271 } else if (notIncludedWithSeq(s, curSequenceNum) 1272 && reverseConnected(s, prevSection, prevSectionDirection)) { 1273 alternateSectionBox.addItem(sName); 1274 alternateSectionBoxList.add(s); 1275 altSectionDirection.add(Section.REVERSE); 1276 } 1277 } 1278 } 1279 // check if there are any Sections available to be inserted at beginning 1280 Section firstSection = sectionList.get(0); 1281 int testDirection = Section.FORWARD; 1282 if (direction.get(0) == Section.FORWARD) { 1283 testDirection = Section.REVERSE; 1284 } 1285 for (Section s : sectionManager.getNamedBeanSet()) { 1286 String sName = s.getDisplayName(); 1287 if ((s != firstSection) && (forwardConnected(s, firstSection, testDirection))) { 1288 insertAtBeginningBox.addItem(sName); 1289 insertAtBeginningBoxList.add(s); 1290 insertAtBeginningDirection.add( Section.REVERSE); 1291 } else if ((s != firstSection) && (reverseConnected(s, firstSection, testDirection))) { 1292 insertAtBeginningBox.addItem(sName); 1293 insertAtBeginningBoxList.add(s); 1294 insertAtBeginningDirection.add( Section.FORWARD); 1295 } 1296 } 1297 } 1298 JComboBoxUtil.setupComboBoxMaxRows(primarySectionBox); 1299 JComboBoxUtil.setupComboBoxMaxRows(alternateSectionBox); 1300 JComboBoxUtil.setupComboBoxMaxRows(insertAtBeginningBox); 1301 } 1302 1303 private boolean forwardConnected(Section s1, Section s2, int restrictedDirection) { 1304 if ((s1 != null) && (s2 != null)) { 1305 List<EntryPoint> s1ForwardEntries = s1.getForwardEntryPointList(); 1306 List<EntryPoint> s2Entries; 1307 switch (restrictedDirection) { 1308 case Section.FORWARD: 1309 s2Entries = s2.getReverseEntryPointList(); 1310 break; 1311 case Section.REVERSE: 1312 s2Entries = s2.getForwardEntryPointList(); 1313 break; 1314 default: 1315 s2Entries = s2.getEntryPointList(); 1316 break; 1317 } 1318 for (int i = 0; i < s1ForwardEntries.size(); i++) { 1319 Block b1 = s1ForwardEntries.get(i).getFromBlock(); 1320 for (int j = 0; j < s2Entries.size(); j++) { 1321 Block b2 = s2Entries.get(j).getFromBlock(); 1322 if ((b1 == s2Entries.get(j).getBlock()) 1323 && (b2 == s1ForwardEntries.get(i).getBlock())) { 1324 return true; 1325 } 1326 } 1327 } 1328 } 1329 return false; 1330 } 1331 1332 private boolean reverseConnected(Section s1, Section s2, int restrictedDirection) { 1333 if ((s1 != null) && (s2 != null)) { 1334 List<EntryPoint> s1ReverseEntries = s1.getReverseEntryPointList(); 1335 List<EntryPoint> s2Entries; 1336 switch (restrictedDirection) { 1337 case Section.FORWARD: 1338 s2Entries = s2.getReverseEntryPointList(); 1339 break; 1340 case Section.REVERSE: 1341 s2Entries = s2.getForwardEntryPointList(); 1342 break; 1343 default: 1344 s2Entries = s2.getEntryPointList(); 1345 break; 1346 } 1347 for (int i = 0; i < s1ReverseEntries.size(); i++) { 1348 Block b1 = s1ReverseEntries.get(i).getFromBlock(); 1349 for (int j = 0; j < s2Entries.size(); j++) { 1350 Block b2 = s2Entries.get(j).getFromBlock(); 1351 if ((b1 == s2Entries.get(j).getBlock()) 1352 && (b2 == s1ReverseEntries.get(i).getBlock())) { 1353 return true; 1354 } 1355 } 1356 } 1357 } 1358 return false; 1359 } 1360 1361 private boolean notIncludedWithSeq(Section s, int seq) { 1362 for (int i = 0; i < sectionList.size(); i++) { 1363 if ((sectionList.get(i) == s) && (seq == sequence.get(i))) { 1364 return false; 1365 } 1366 } 1367 return true; 1368 } 1369 1370 private void autoSystemName() { 1371 if (_autoSystemName.isSelected()) { 1372// create.setEnabled(true); 1373 sysName.setEnabled(false); 1374 sysNameLabel.setEnabled(false); 1375 } else { 1376// if (sysName.getText().length() > 0) 1377// create.setEnabled(true); 1378// else 1379// create.setEnabled(false); 1380 sysName.setEnabled(true); 1381 sysNameLabel.setEnabled(true); 1382 } 1383 } 1384 1385 // variables for View Actions window 1386 private int activeRow = 0; 1387 private SpecialActionTableModel actionTableModel = null; 1388 private JmriJFrame actionTableFrame = null; 1389 private final JLabel fixedSectionLabel = new JLabel("X"); 1390 1391 private void addEditActionsPressed(int r) { 1392 activeRow = r; 1393 if (actionTableModel != null) { 1394 actionTableModel.fireTableStructureChanged(); 1395 } 1396 if (actionTableFrame == null) { 1397 actionTableFrame = new JmriJFrame(rbx.getString("TitleViewActions")); 1398 actionTableFrame.addHelpMenu( 1399 "package.jmri.jmrit.beantable.ViewSpecialActions", true); 1400 Container contentPane = actionTableFrame.getContentPane(); 1401 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 1402 JPanel panel1 = new JPanel(); 1403 panel1.setLayout(new FlowLayout()); 1404 JLabel sectionNameLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("BeanNameSection"))); 1405 panel1.add(sectionNameLabel); 1406 panel1.add(fixedSectionLabel); 1407 contentPane.add(panel1); 1408 addFrame.getContentPane().add(new JSeparator()); 1409 JPanel pct = new JPanel(); 1410 pct.setLayout(new BorderLayout()); 1411 // initialize table of actions 1412 actionTableModel = new SpecialActionTableModel(); 1413 JTable actionTable = new JTable(actionTableModel); 1414 actionTable.setRowSelectionAllowed(false); 1415 TableColumnModel actionColumnModel = actionTable 1416 .getColumnModel(); 1417 TableColumn whenColumn = actionColumnModel 1418 .getColumn(SpecialActionTableModel.WHEN_COLUMN); 1419 whenColumn.setResizable(true); 1420 TableColumn whatColumn = actionColumnModel 1421 .getColumn(SpecialActionTableModel.WHAT_COLUMN); 1422 whatColumn.setResizable(true); 1423 TableColumn editColumn = actionColumnModel 1424 .getColumn(SpecialActionTableModel.EDIT_COLUMN); 1425 // install button renderer and editor 1426 ButtonRenderer buttonRenderer = new ButtonRenderer(); 1427 actionTable.setDefaultRenderer(JButton.class, buttonRenderer); 1428 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 1429 actionTable.setDefaultEditor(JButton.class, buttonEditor); 1430 JButton testButton = new JButton(Bundle.getMessage("ButtonDelete")); 1431 actionTable.setRowHeight(testButton.getPreferredSize().height); 1432 editColumn.setResizable(false); 1433 editColumn.setMinWidth(testButton.getPreferredSize().width); 1434 editColumn.setMaxWidth(testButton.getPreferredSize().width); 1435 TableColumn removeColumn = actionColumnModel 1436 .getColumn(SpecialActionTableModel.REMOVE_COLUMN); 1437 removeColumn.setMinWidth(testButton.getPreferredSize().width); 1438 removeColumn.setMaxWidth(testButton.getPreferredSize().width); 1439 removeColumn.setResizable(false); 1440 JScrollPane actionTableScrollPane = new JScrollPane( 1441 actionTable); 1442 pct.add(actionTableScrollPane, BorderLayout.CENTER); 1443 contentPane.add(pct); 1444 pct.setVisible(true); 1445 // add View Action panel buttons 1446 JPanel but = new JPanel(); 1447 but.setLayout(new BoxLayout(but, BoxLayout.Y_AXIS)); 1448 JPanel panel4 = new JPanel(); 1449 panel4.setLayout(new FlowLayout()); 1450 JButton newActionButton = new JButton(rbx.getString("ButtonAddNewAction")); 1451 panel4.add(newActionButton); 1452 newActionButton.addActionListener(this::newActionPressed); 1453 newActionButton.setToolTipText(rbx.getString("NewActionButtonHint")); 1454 JButton doneButton = new JButton(Bundle.getMessage("ButtonDone")); 1455 panel4.add(doneButton); 1456 doneButton.addActionListener(this::doneWithActionsPressed); 1457 doneButton.setToolTipText(rbx.getString("DoneButtonHint")); 1458 but.add(panel4); 1459 contentPane.add(but); 1460 } 1461 fixedSectionLabel.setText(getSectionNameByRow(r) + " " 1462 + rbx.getString("SequenceAbbrev") + ": " + sequence.get(r)); 1463 actionTableFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1464 @Override 1465 public void windowClosing(java.awt.event.WindowEvent e) { 1466 actionTableFrame.setVisible(false); 1467 actionTableFrame.dispose(); 1468 actionTableFrame = null; 1469 if (addEditActionFrame != null) { 1470 addEditActionFrame.setVisible(false); 1471 addEditActionFrame.dispose(); 1472 addEditActionFrame = null; 1473 } 1474 } 1475 }); 1476 actionTableFrame.pack(); 1477 actionTableFrame.setVisible(true); 1478 } 1479 1480 private void doneWithActionsPressed(ActionEvent e) { 1481 actionTableFrame.setVisible(false); 1482 actionTableFrame.dispose(); 1483 actionTableFrame = null; 1484 if (addEditActionFrame != null) { 1485 addEditActionFrame.setVisible(false); 1486 addEditActionFrame.dispose(); 1487 addEditActionFrame = null; 1488 } 1489 } 1490 1491 private void newActionPressed(ActionEvent e) { 1492 editActionMode = false; 1493 curTSA = null; 1494 addEditActionWindow(); 1495 } 1496 1497 // variables for Add/Edit Action window 1498 private boolean editActionMode = false; 1499 private JmriJFrame addEditActionFrame = null; 1500 private TransitSectionAction curTSA = null; 1501 private final JComboBox<String> whenBox = new JComboBox<>(); 1502 private final NamedBeanComboBox<Sensor> whenSensorComboBox = new NamedBeanComboBox<>( 1503 InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME); 1504 private final JSpinner whenDataSpinnerFloat = new JSpinner(new SpinnerNumberModel( 1505 Float.valueOf(0.0f), Float.valueOf(0.0f), Float.valueOf(65.0f), Float.valueOf(0.5f))); // delay 1506 private final JSpinner whenDataSpinnerInt = new JSpinner(new SpinnerNumberModel(0, 0, 65000, 100)); // delay 1507 private final JRadioButton mSecButton = new JRadioButton(Bundle.getMessage("LabelMilliseconds")); 1508 private final JRadioButton secButton = new JRadioButton(Bundle.getMessage("LabelSeconds")); 1509 private final JComboBox<String> whatBox = new JComboBox<>(); 1510 private final JSpinner whatPercentSpinner = new JSpinner(); // speed 1511 private final JSpinner whatMinuteSpinner1 = new JSpinner(new SpinnerNumberModel(1, 1, 65500, 1)); // time in ms 1512 private final JSpinner whatMinuteSpinner2 = new JSpinner(new SpinnerNumberModel(100, 100, 65500, 1)); // time in ms 1513 private final JSpinner locoFunctionSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 28, 1)); // function ID 1514 private final JTextField whatStringField = new JTextField(12); 1515 private final JTextField locoAddress = new JTextField(12); 1516 private final RosterEntryComboBox rosterComboBox = new RosterEntryComboBox(); 1517 private final JComboBox<String> trainInfoComboBox = new JComboBox<>(); 1518 private final JRadioButton locoAddressDefault = new JRadioButton(rbx.getString("TrainInfoUseDefault")); 1519 private final JRadioButton locoAddressRoster = new JRadioButton(rbx.getString("TrainInfoUseRoster")); 1520 private final JRadioButton locoAddressNumber = new JRadioButton(rbx.getString("TrainInfoUseAddress")); 1521 private final JRadioButton locoAddressCurrent = new JRadioButton(rbx.getString("TrainInfoUseCurrentAddress")); 1522 private final ButtonGroup locoAddressGroup = new ButtonGroup(); 1523 private JButton updateActionButton = null; 1524 private JButton createActionButton = null; 1525 private JButton cancelAddEditActionButton = null; 1526 private final JComboBox<String> blockBox = new JComboBox<>(); 1527 private List<Block> blockList = new ArrayList<>(); 1528 private final JRadioButton onButton = new JRadioButton(Bundle.getMessage("StateOn")); 1529 private final JRadioButton offButton = new JRadioButton(Bundle.getMessage("StateOff")); 1530 private final JLabel doneSensorLabel = new JLabel(rbx.getString("DoneSensorLabel")); 1531 private JPanel signalPanel; 1532 private JPanel panelPercentageSpinner; 1533 private JPanel panelDelay; 1534 private final JLabel panelDelayLabel = new JLabel(); 1535 private JPanel panelWhatBox; 1536 private JPanel panelLoadTrainInfo; 1537 private final NamedBeanComboBox<Sensor> doneSensorComboBox = new NamedBeanComboBox<>( 1538 InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME); 1539 private final NamedBeanComboBox<SignalMast> signalMastComboBox = new NamedBeanComboBox<>( 1540 InstanceManager.getDefault(SignalMastManager.class), null, DisplayOptions.DISPLAYNAME); 1541 private final NamedBeanComboBox<SignalHead> signalHeadComboBox = new NamedBeanComboBox<>( 1542 InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME); 1543 1544 private void addEditActionWindow() { 1545 if (addEditActionFrame == null) { 1546 // set up add/edit action window 1547 addEditActionFrame = new JmriJFrame(rbx.getString("TitleAddAction")); 1548 addEditActionFrame.addHelpMenu( 1549 "package.jmri.jmrit.beantable.TransitSectionAddEditAction", true); 1550 Container contentPane = addEditActionFrame.getContentPane(); 1551 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 1552 // to set When to start the action 1553 JPanel panelx = new JPanel(); 1554 panelx.setLayout(new BoxLayout(panelx, BoxLayout.Y_AXIS)); 1555 JPanel panel1 = new JPanel(); 1556 panel1.setLayout(new FlowLayout()); 1557 panel1.add(new JLabel(rbx.getString("WhenText"))); 1558 initializeWhenBox(); 1559 JComboBoxUtil.setupComboBoxMaxRows(whenBox); 1560 panel1.add(whenBox); 1561 whenBox.addActionListener((ActionEvent e) -> { 1562 log.debug("whenBox was set"); 1563 if (whenBox.getSelectedItem()!=null) { 1564 setWhen(getWhenMenuCode((String)whenBox.getSelectedItem())); 1565 } 1566 }); 1567 whenBox.setToolTipText(rbx.getString("WhenBoxTip")); 1568 JComboBoxUtil.setupComboBoxMaxRows(whenSensorComboBox); 1569 panel1.add(whenSensorComboBox); 1570 whenSensorComboBox.setAllowNull(true); 1571 initializeBlockBox(); 1572 JComboBoxUtil.setupComboBoxMaxRows(blockBox); 1573 panel1.add(blockBox); 1574 panelx.add(panel1); 1575 // to set optional delay setting 1576 panelDelay = new JPanel(); 1577 panelDelay.setLayout(new FlowLayout()); 1578 panelDelayLabel.setText(" " + rbx.getString("OptionalDelay") + ": "); 1579 panelDelay.add(panelDelayLabel); 1580 panelDelay.add(whenDataSpinnerInt); 1581 whenDataSpinnerInt.setToolTipText(rbx.getString("HintDelayData")); 1582 whenDataSpinnerInt.addChangeListener((ChangeEvent e) -> { 1583 if (mSecButton.isSelected()) { 1584 float fl = (int)whenDataSpinnerInt.getValue(); 1585 whenDataSpinnerFloat.setValue(fl/1000.0f); 1586 } 1587 }); 1588 panelDelay.add(whenDataSpinnerFloat); 1589 whenDataSpinnerFloat.setToolTipText(rbx.getString("HintDelayData")); 1590 whenDataSpinnerFloat.setPreferredSize(whenDataSpinnerInt.getPreferredSize()); 1591 whenDataSpinnerFloat.addChangeListener( e -> { 1592 if (secButton.isSelected()) { 1593 float dVal = (float)whenDataSpinnerFloat.getValue(); 1594 dVal *= 1000.0; 1595 whenDataSpinnerInt.setValue(Math.round(dVal)); 1596 } 1597 }); 1598 ButtonGroup secMsec = new ButtonGroup(); 1599 secMsec.add(mSecButton); 1600 secMsec.add(secButton); 1601 panelDelay.add(mSecButton); 1602 mSecButton.addChangeListener( e -> { 1603 if (mSecButton.isSelected()) { 1604 whenDataSpinnerFloat.setVisible(false); 1605 whenDataSpinnerInt.setVisible(true); 1606 } 1607 }); 1608 panelDelay.add(secButton); 1609 secButton.addChangeListener( e -> { 1610 if (secButton.isSelected()) { 1611 whenDataSpinnerFloat.setVisible(true); 1612 whenDataSpinnerInt.setVisible(false); 1613 } 1614 }); 1615 secButton.setSelected(true); 1616 panelx.add(panelDelay); 1617 JPanel spacer = new JPanel(); 1618 spacer.setLayout(new FlowLayout()); 1619 spacer.add(new JLabel(" ")); 1620 panelx.add(spacer); 1621 // to set What action to take 1622 panelWhatBox = new JPanel(); 1623 panelWhatBox.setLayout(new FlowLayout()); 1624 panelWhatBox.add(new JLabel(rbx.getString("WhatText"))); 1625 initializeWhatBox(0); 1626 JComboBoxUtil.setupComboBoxMaxRows(whatBox); 1627 panelWhatBox.add(whatBox); 1628 whatBox.setToolTipText(rbx.getString("WhatBoxTip")); 1629 whatBox.addActionListener( e -> { 1630 if (whatBox.getSelectedItem()!=null) { 1631 setWhat(getWhatMenuCode((String)whatBox.getSelectedItem())); 1632 } 1633 }); 1634 panelWhatBox.add(whatStringField); 1635 whatStringField.setToolTipText(rbx.getString("HintSoundHornPatternString")); 1636 panelx.add(panelWhatBox); 1637 1638 // Train Info 1639 TitledBorder trainInfoBorder = BorderFactory.createTitledBorder(rbx.getString("SelectTrain")); 1640 panelLoadTrainInfo = new JPanel(); 1641 panelLoadTrainInfo.setLayout(new BoxLayout(panelLoadTrainInfo, BoxLayout.Y_AXIS)); 1642 panelLoadTrainInfo.setBorder(trainInfoBorder); 1643 JPanel panelUseInfo = new JPanel(); 1644 panelUseInfo.setBorder(trainInfoBorder); 1645 panelUseInfo.add(new JLabel(rbx.getString("TrainInfoFile"))); 1646 panelUseInfo.add(trainInfoComboBox); 1647 trainInfoComboBox.setToolTipText(rbx.getString("HintTrainInfoFile")); 1648 panelLoadTrainInfo.add(panelUseInfo); 1649 TitledBorder useLocoBorder = BorderFactory.createTitledBorder(rbx.getString("SelectALoco")); 1650 JPanel panelUseLoco = new JPanel(); 1651 panelUseLoco.setBorder(useLocoBorder); 1652 1653 locoAddressGroup.add(locoAddressDefault); 1654 locoAddressDefault.setToolTipText(rbx.getString("TrainInfoUseDefaultHint")); 1655 locoAddressDefault.addActionListener(this::updateTrainInfoAddressFields); 1656 panelUseLoco.add(locoAddressDefault); 1657 locoAddressGroup.add(locoAddressCurrent); 1658 locoAddressCurrent.setToolTipText(rbx.getString("TrainInfoUseCurrentAddressHint")); 1659 locoAddressCurrent.addActionListener(this::updateTrainInfoAddressFields); 1660 panelUseLoco.add(locoAddressCurrent); 1661 locoAddressGroup.add(locoAddressRoster); 1662 locoAddressRoster.addActionListener(this::updateTrainInfoAddressFields); 1663 panelUseLoco.add(locoAddressRoster); 1664 locoAddressGroup.add(locoAddressNumber); 1665 locoAddressNumber.addActionListener(this::updateTrainInfoAddressFields); 1666 panelUseLoco.add(locoAddressNumber); 1667 panelUseLoco.add(locoAddress); 1668 locoAddress.setToolTipText(rbx.getString("HintLocoMotiveAddress")); 1669 panelUseLoco.add(rosterComboBox); 1670 panelLoadTrainInfo.add(panelUseLoco); 1671 panelx.add(panelLoadTrainInfo); 1672 panelLoadTrainInfo.setVisible(false); 1673 1674 panelPercentageSpinner = new JPanel(); 1675 panelPercentageSpinner.setLayout(new FlowLayout()); 1676 whatPercentSpinner.setModel(new SpinnerNumberModel( 1677 Float.valueOf(1.0f), Float.valueOf(0.00f), Float.valueOf(1.5f), Float.valueOf(0.01f))); 1678 whatPercentSpinner.setEditor(new JSpinner.NumberEditor(whatPercentSpinner, "# %")); // show as a percentage % sign 1679 panelPercentageSpinner.add(whatPercentSpinner); 1680 panelPercentageSpinner.add(whatMinuteSpinner1); 1681 panelPercentageSpinner.add(whatMinuteSpinner2); 1682 panelPercentageSpinner.add(locoFunctionSpinner); 1683 // signal comboboxes 1684 TitledBorder border = BorderFactory.createTitledBorder(rbx.getString("SelectASignal")); 1685 signalPanel = new JPanel(); 1686 signalPanel.setBorder(border); 1687 signalPanel.add(new JLabel(rbx.getString("MastLabel"))); 1688 JComboBoxUtil.setupComboBoxMaxRows(signalMastComboBox); 1689 signalPanel.add(signalMastComboBox); 1690 signalMastComboBox.setAllowNull(true); 1691 signalMastComboBox.addActionListener((ActionEvent e) -> { 1692 if (signalMastComboBox.getSelectedIndex() > 0) { 1693 signalHeadComboBox.setSelectedIndex(-1); // choose either a head or a mast 1694 } 1695 }); 1696 signalPanel.add(new JLabel(rbx.getString("HeadLabel"))); 1697 JComboBoxUtil.setupComboBoxMaxRows(signalHeadComboBox); 1698 signalPanel.add(signalHeadComboBox); 1699 signalHeadComboBox.setAllowNull(true); 1700 signalHeadComboBox.addActionListener((ActionEvent e) -> { 1701 if (signalHeadComboBox.getSelectedIndex() > 0) { 1702 signalMastComboBox.setSelectedIndex(-1); // choose either a head or a mast 1703 } 1704 }); 1705 signalMastComboBox.setToolTipText(rbx.getString("HintSignalEntry")); 1706 signalHeadComboBox.setToolTipText(rbx.getString("HintSignalEntry")); 1707 panelPercentageSpinner.add(signalPanel); 1708 // On/Off buttons 1709 ButtonGroup onOffGroup = new ButtonGroup(); 1710 onOffGroup.add(onButton); 1711 onOffGroup.add(offButton); 1712 panelPercentageSpinner.add(onButton); 1713 panelPercentageSpinner.add(offButton); 1714 panelPercentageSpinner.add(doneSensorLabel); 1715 panelPercentageSpinner.add(doneSensorComboBox); 1716 JComboBoxUtil.setupComboBoxMaxRows(doneSensorComboBox); 1717 doneSensorComboBox.setAllowNull(true); 1718 panelx.add(panelPercentageSpinner); 1719 contentPane.add(panelx); 1720 contentPane.add(new JSeparator()); 1721 // add buttons 1722 JPanel but = new JPanel(); 1723 but.setLayout(new FlowLayout()); 1724 but.add(cancelAddEditActionButton = new JButton(Bundle.getMessage("ButtonCancel"))); 1725 cancelAddEditActionButton.addActionListener(this::cancelAddEditActionPressed); 1726 cancelAddEditActionButton.setToolTipText(rbx.getString("CancelButtonHint")); 1727 createActionButton = new JButton(rbx.getString("CreateActionButton")); 1728 but.add(createActionButton); 1729 createActionButton.addActionListener(this::createActionPressed); 1730 createActionButton.setToolTipText(rbx.getString("CreateActionButtonHint")); 1731 updateActionButton = new JButton(rbx.getString("UpdateActionButton")); 1732 but.add(updateActionButton); 1733 updateActionButton.addActionListener(this::updateActionPressed); 1734 updateActionButton.setToolTipText(rbx.getString("UpdateActionButtonHint")); 1735 contentPane.add(but); 1736 } 1737 if (editActionMode) { 1738 // initialize window for the action being edited 1739 addEditActionFrame.setTitle(rbx.getString("TitleEditAction")); 1740 updateActionButton.setVisible(true); 1741 createActionButton.setVisible(false); 1742 whenDataSpinnerInt.setValue(curTSA.getDataWhen()); 1743 float whenFloat = (int)whenDataSpinnerInt.getValue(); 1744 whenDataSpinnerFloat.setValue(whenFloat/1000.0f); 1745 whenSensorComboBox.setSelectedItemByName(curTSA.getStringWhen()); 1746 // spinners are set in setWhat() 1747 tWhatString2 = curTSA.getStringWhat2(); 1748 tWhatString = curTSA.getStringWhat(); 1749 tWhatData1 = curTSA.getDataWhat1(); 1750 tWhat = curTSA.getWhatCode(); 1751 tWhen = curTSA.getWhenCode(); 1752 tWhenData = curTSA.getDataWhen(); 1753 tWhatData2 = curTSA.getDataWhat2(); 1754 whatStringField.setText(tWhatString); 1755 onButton.setSelected(true); 1756 if ("Off".equals(curTSA.getStringWhat())) { 1757 offButton.setSelected(true); 1758 } 1759 locoAddress.setText(curTSA.getStringWhat2()); 1760 panelLoadTrainInfo.setVisible(false); 1761 log.debug("setWhen called for edit of action, editmode = {}", editActionMode); 1762 whenBox.setSelectedItem(getWhenMenuText(curTSA.getWhenCode())); 1763 // setWhen(curTSA.getWhenCode()) and setWhat(idem) are set via whenBox and whatBox 1764 whatBox.setSelectedItem(getWhatMenuText(curTSA.getWhatCode())); 1765 setBlockBox(); 1766 } else { 1767 // initialize for add new action 1768 addEditActionFrame.setTitle(rbx.getString("TitleAddAction")); 1769 whenBox.setSelectedIndex(0); 1770 // setWhen(1) and setWhat(1) are set from the whenBox and whatBox listeners 1771 whatBox.setSelectedIndex(0); 1772 // set initial values after setting model 1773 whenDataSpinnerInt.setValue(0); 1774 whenDataSpinnerFloat.setValue(0.0f); 1775 whenSensorComboBox.setSelectedItem(0); 1776 whatPercentSpinner.setValue(1.0f); 1777 whatMinuteSpinner1.setValue(100); 1778 whatMinuteSpinner2.setValue(100); 1779 locoFunctionSpinner.setValue(0); 1780 signalMastComboBox.setSelectedItem(0); 1781 signalHeadComboBox.setSelectedItem(0); 1782 doneSensorComboBox.setSelectedItem(0); 1783 whatStringField.setText(""); 1784 locoAddress.setText(""); 1785 onButton.setSelected(true); 1786 updateActionButton.setVisible(false); 1787 createActionButton.setVisible(true); 1788 panelLoadTrainInfo.setVisible(false); 1789 setBlockBox(); 1790 } 1791 addEditActionFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1792 @Override 1793 public void windowClosing(java.awt.event.WindowEvent e) { 1794 addEditActionFrame.setVisible(false); 1795 addEditActionFrame.dispose(); 1796 addEditActionFrame = null; 1797 } 1798 }); 1799 addEditActionFrame.pack(); 1800 addEditActionFrame.setVisible(true); 1801 } 1802 1803 /** 1804 * Set special stuff depending on When selected. 1805 * 1806 * @param code selected item in getWhenBox 1807 */ 1808 private void setWhen(int code) { 1809 // setting the whenBox here causes recursion 1810 whenSensorComboBox.setVisible(false); 1811 blockBox.setVisible(false); 1812 panelDelay.setVisible(true); 1813 panelWhatBox.setVisible(true); 1814 panelPercentageSpinner.setVisible(true); 1815 panelDelayLabel.setText(" " + rbx.getString("OptionalDelay") + ": "); 1816 log.debug("setWhen code = {}", code); 1817 initializeWhatBox(code); 1818 switch (code) { 1819 case TransitSectionAction.EXIT: 1820 panelDelay.setVisible(false); 1821 break; 1822 case TransitSectionAction.ENTRY: 1823 case TransitSectionAction.TRAINSTOP: 1824 case TransitSectionAction.TRAINSTART: 1825 case TransitSectionAction.PRESTARTACTION: 1826 break; 1827 case TransitSectionAction.PRESTARTDELAY: 1828 panelDelay.setVisible(true); 1829 panelDelayLabel.setText(" " + rbx.getString("Delay") + ": "); 1830 panelWhatBox.setVisible(false); 1831 panelPercentageSpinner.setVisible(false); 1832 break; 1833 case TransitSectionAction.BLOCKENTRY: 1834 case TransitSectionAction.BLOCKEXIT: 1835 blockBox.setVisible(true); 1836 blockBox.setToolTipText(rbx.getString("HintBlockEntry")); 1837 break; 1838 case TransitSectionAction.SENSORACTIVE: 1839 case TransitSectionAction.SENSORINACTIVE: 1840 whenSensorComboBox.setVisible(true); 1841 whenSensorComboBox.setToolTipText(rbx.getString("HintSensorEntry")); 1842 break; 1843 case TransitSectionAction.SELECTWHEN: 1844 break; 1845 default: 1846 log.debug("Unhandled transit action code: {}", code); // causes too much noise, no harm done hiding it 1847 } 1848 addEditActionFrame.pack(); 1849 addEditActionFrame.setVisible(true); 1850 } 1851 1852 /** 1853 * Set special stuff depending on What selected, including spinner value. 1854 * 1855 * @param code selected item in getWhatBox 1856 */ 1857 private void setWhat(int code) { 1858 // setting the whatBox here causes recursion 1859 // hide all input boxes, set those needed visible via a switch case 1860 whatStringField.setVisible(false); 1861 whatPercentSpinner.setVisible(false); 1862 whatMinuteSpinner1.setVisible(false); 1863 whatMinuteSpinner2.setVisible(false); 1864 locoFunctionSpinner.setVisible(false); 1865 signalPanel.setVisible(false); 1866 onButton.setVisible(false); 1867 offButton.setVisible(false); 1868 doneSensorLabel.setVisible(false); 1869 doneSensorComboBox.setVisible(false); 1870 panelDelay.setEnabled(true); 1871 panelLoadTrainInfo.setVisible(false); 1872 log.debug("setWhat code = {}", code); 1873 switch (code) { 1874 case TransitSectionAction.TERMINATETRAIN: 1875 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 1876 break; 1877 1878 case TransitSectionAction.LOADTRAININFO: 1879 rosterComboBox.update(); 1880 String[] names = new TrainInfoFile().getTrainInfoFileNames(); 1881 trainInfoComboBox.removeAllItems(); 1882 for (String fn: names) { 1883 trainInfoComboBox.addItem(fn); 1884 if (fn.equals(tWhatString)) { 1885 trainInfoComboBox.setSelectedItem(fn); 1886 } 1887 } 1888 locoAddress.setText(Integer.toString(tWhatData1)); 1889 switch (tWhatData2) { 1890 case TransitSectionAction.LOCOADDRESSTYPEROSTER: 1891 locoAddressRoster.setSelected(true); 1892 setRosterComboBox(rosterComboBox, tWhatString2); 1893 rosterComboBox.setVisible(true); 1894 locoAddress.setVisible(false); 1895 break; 1896 case TransitSectionAction.LOCOADDRESSTYPENUMBER: 1897 locoAddressNumber.setSelected(true); 1898 locoAddress.setText(tWhatString2); 1899 rosterComboBox.setVisible(false); 1900 locoAddress.setVisible(true); 1901 break; 1902 case TransitSectionAction.LOCOADDRESSTYPECURRENT: 1903 locoAddressCurrent.setSelected(true); 1904 locoAddress.setText(""); 1905 rosterComboBox.setVisible(false); 1906 locoAddress.setVisible(false); 1907 break; 1908 case TransitSectionAction.LOCOADDRESSTYPEDEFAULT: 1909 default: 1910 locoAddressDefault.setSelected(true); 1911 rosterComboBox.setVisible(false); 1912 locoAddress.setVisible(false); 1913 locoAddress.setText(""); 1914 break; 1915 } 1916 panelLoadTrainInfo.setVisible(true); 1917 break; 1918 case TransitSectionAction.PAUSE: 1919 if (getWhenMenuCode((String)whenBox.getSelectedItem()) == TransitSectionAction.PRESTARTDELAY) { 1920 panelDelay.setEnabled(false); 1921 } 1922 whatMinuteSpinner1.setModel(new SpinnerNumberModel(1, 1, 65500, 1)); 1923 if (editActionMode) { 1924 whatMinuteSpinner1.setValue(Math.max(curTSA.getDataWhat1(), 1)); 1925 } 1926 whatMinuteSpinner1.setVisible(true); 1927 whatMinuteSpinner1.setToolTipText(rbx.getString("HintPauseData")); 1928 break; 1929 case TransitSectionAction.SETMAXSPEED: 1930 case TransitSectionAction.SETCURRENTSPEED: 1931 case TransitSectionAction.RAMPTRAINSPEED: 1932 if (editActionMode) { 1933 float maxPerc = Math.max(0.01f * curTSA.getDataWhat1(), 0.0f); 1934 whatPercentSpinner.setValue(maxPerc); 1935 } 1936 whatPercentSpinner.setVisible(true); 1937 whatPercentSpinner.setToolTipText(rbx.getString("HintSetSpeedData1")); 1938 break; 1939 case TransitSectionAction.TOMANUALMODE: 1940 if (editActionMode) { 1941 doneSensorComboBox.setSelectedItemByName(curTSA.getStringWhat()); 1942 } 1943 doneSensorLabel.setVisible(true); 1944 doneSensorComboBox.setVisible(true); 1945 doneSensorComboBox.setToolTipText(rbx.getString("HintDoneSensor")); 1946 break; 1947 case TransitSectionAction.SETLIGHT: 1948 onButton.setVisible(true); 1949 offButton.setVisible(true); 1950 onButton.setToolTipText(rbx.getString("HintSetLight")); 1951 offButton.setToolTipText(rbx.getString("HintSetLight")); 1952 break; 1953 case TransitSectionAction.STARTBELL: 1954 break; 1955 case TransitSectionAction.STOPBELL: 1956 break; 1957 case TransitSectionAction.SOUNDHORN: 1958 whatMinuteSpinner1.setValue(100); 1959 whatMinuteSpinner1.setModel(new SpinnerNumberModel(100, 100, 65500, 1)); 1960 if (editActionMode) { 1961 whatMinuteSpinner1.setValue(curTSA.getDataWhat1()); 1962 } 1963 if ((Integer) whatMinuteSpinner1.getValue() < 100) { 1964 whatMinuteSpinner1.setValue(100); // might result from user changing from PAUSE to SOUNDHORN 1965 } 1966 whatMinuteSpinner1.setVisible(true); 1967 whatMinuteSpinner1.setToolTipText(rbx.getString("HintSoundHornData1")); 1968 break; 1969 case TransitSectionAction.SOUNDHORNPATTERN: 1970 whatMinuteSpinner1.setValue(100); 1971 whatMinuteSpinner1.setModel(new SpinnerNumberModel(100, 100, 65500, 1)); 1972 // whatMinuteSpinner2 model never changes 1973 if (editActionMode) { 1974 whatMinuteSpinner1.setValue(curTSA.getDataWhat1()); 1975 whatMinuteSpinner2.setValue(Math.max(curTSA.getDataWhat2(), 100)); 1976 // might result from user changing from sth.else to SOUNDHORNPATTERN 1977 } 1978 if ((Integer) whatMinuteSpinner1.getValue() < 100) { 1979 whatMinuteSpinner1.setValue(100); // might result from user changing from PAUSE to SOUNDHORNPATTERN 1980 } 1981 whatMinuteSpinner1.setVisible(true); 1982 whatMinuteSpinner1.setToolTipText(rbx.getString("HintSoundHornPatternData1")); 1983 whatMinuteSpinner2.setVisible(true); 1984 whatMinuteSpinner2.setToolTipText(rbx.getString("HintSoundHornPatternData2")); 1985 whatStringField.setVisible(true); 1986 break; 1987 case TransitSectionAction.LOCOFUNCTION: 1988 if (editActionMode) { 1989 locoFunctionSpinner.setValue(curTSA.getDataWhat1()); 1990 } 1991 locoFunctionSpinner.setVisible(true); 1992 locoFunctionSpinner.setToolTipText(rbx.getString("HintLocoFunctionData1")); 1993 onButton.setVisible(true); 1994 offButton.setVisible(true); 1995 onButton.setToolTipText(rbx.getString("HintLocoFunctionOnOff")); 1996 offButton.setToolTipText(rbx.getString("HintLocoFunctionOnOff")); 1997 break; 1998 case TransitSectionAction.SETSENSORACTIVE: 1999 case TransitSectionAction.SETSENSORINACTIVE: 2000 if (editActionMode) { 2001 doneSensorComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2002 } 2003 doneSensorComboBox.setVisible(true); 2004 doneSensorComboBox.setToolTipText(rbx.getString("HintSensorEntry")); 2005 break; 2006 case TransitSectionAction.HOLDSIGNAL: 2007 case TransitSectionAction.RELEASESIGNAL: 2008 if (editActionMode) { 2009 SignalMast sm = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(curTSA.getStringWhat()); 2010 if (sm != null) { // name is an existing mast 2011 signalMastComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2012 } else { 2013 SignalHead sh = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(curTSA.getStringWhat()); 2014 if (sh != null) { // name is an existing head 2015 signalHeadComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2016 } 2017 } 2018 } 2019 signalPanel.setVisible(true); 2020 break; 2021 case TransitSectionAction.ESTOP: 2022 default: 2023 log.debug("Unhandled transit section action: {}", code); // causes too much noise, no harm done hiding it 2024 break; 2025 } 2026 addEditActionFrame.pack(); 2027 addEditActionFrame.setVisible(true); 2028 } 2029 2030 private boolean setRosterComboBox(RosterEntryComboBox box, String txt) { 2031 boolean found = false; 2032 for (int i = 1; i < box.getItemCount(); i++) { 2033 if (txt.equals(((RosterEntry) box.getItemAt(i)).getId())) { 2034 box.setSelectedIndex(i); 2035 found = true; 2036 break; 2037 } 2038 } 2039 if (!found && box.getItemCount() > 0) { 2040 box.setSelectedIndex(0); 2041 } 2042 return found; 2043 } 2044 2045 private void updateTrainInfoAddressFields(ActionEvent e) { 2046 if (!((JRadioButton)e.getSource()).isSelected() ) { 2047 return; 2048 } 2049 if (e.getSource() == locoAddressRoster) { 2050 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEROSTER; 2051 rosterComboBox.setVisible(true); 2052 locoAddress.setVisible(false); 2053 } else if (e.getSource() == locoAddressNumber) { 2054 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPENUMBER; 2055 rosterComboBox.setVisible(false); 2056 locoAddress.setVisible(true); 2057 } else if (e.getSource() == locoAddressDefault) { 2058 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEDEFAULT; 2059 rosterComboBox.setVisible(false); 2060 locoAddress.setVisible(false); 2061 } else if (e.getSource() == locoAddressCurrent) { 2062 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPECURRENT; 2063 rosterComboBox.setVisible(false); 2064 locoAddress.setVisible(false); 2065 } else { 2066 log.warn("Unknown button Source"); 2067 } 2068 } 2069 2070 // temporary action variables 2071 private int tWhen = 0; 2072 private int tWhenData = 0; 2073 private String tWhenString = ""; 2074 private int tWhat = 0; 2075 private int tWhatData1 = 0; 2076 private int tWhatData2 = 0; 2077 private String tWhatString = ""; 2078 private String tWhatString2 = ""; 2079 2080 /** 2081 * Handle button presses in Add/Edit Transit Action window. 2082 * 2083 * @param e the event seen 2084 */ 2085 private void createActionPressed(ActionEvent e) { 2086 if ((!validateWhenData()) || (!validateWhatData())) { 2087 return; 2088 } 2089 // entered data is OK, create a special action 2090 curTSA = new TransitSectionAction(tWhen, tWhat, tWhenData, tWhatData1, tWhatData2, tWhenString, tWhatString, tWhatString2); 2091 List<TransitSectionAction> list = action.get(activeRow); 2092 list.add(curTSA); 2093 actionTableModel.fireTableDataChanged(); 2094 addEditActionFrame.setVisible(false); 2095 addEditActionFrame.dispose(); 2096 addEditActionFrame = null; 2097 } 2098 2099 private void updateActionPressed(ActionEvent e) { 2100 if ((!validateWhenData()) || (!validateWhatData())) { 2101 return; 2102 } 2103 // entered data is OK, update the current special action 2104 curTSA.setWhenCode(tWhen); 2105 curTSA.setWhatCode(tWhat); 2106 curTSA.setDataWhen(tWhenData); 2107 curTSA.setDataWhat1(tWhatData1); 2108 curTSA.setDataWhat2(tWhatData2); 2109 curTSA.setStringWhen(tWhenString); 2110 curTSA.setStringWhat(tWhatString); 2111 curTSA.setStringWhat2(tWhatString2); 2112 actionTableModel.fireTableDataChanged(); 2113 addEditActionFrame.setVisible(false); 2114 addEditActionFrame.dispose(); 2115 addEditActionFrame = null; 2116 } 2117 2118 private void cancelAddEditActionPressed(ActionEvent e) { 2119 addEditActionFrame.setVisible(false); 2120 addEditActionFrame.dispose(); 2121 addEditActionFrame = null; 2122 } 2123 2124 private boolean validateWhenData() { 2125 tWhen = getWhenMenuCode((String)whenBox.getSelectedItem()); 2126 tWhenData = (int)whenDataSpinnerInt.getValue(); 2127 tWhenString = ""; 2128 if (tWhen == TransitSectionAction.PRESTARTDELAY ) { 2129 // must have a delay 2130 if (tWhenData <1 ) { 2131 return false; 2132 } 2133 } 2134 if ((tWhen == TransitSectionAction.SENSORACTIVE) || (tWhen == TransitSectionAction.SENSORINACTIVE)) { 2135 if (whenSensorComboBox.getSelectedIndex() != 0) { // it's optional, so might be 0 2136 tWhenString = whenSensorComboBox.getSelectedItemSystemName(); 2137 } 2138 if (!validateSensor(tWhenString, true)) { 2139 return false; 2140 } 2141 } 2142 if ((tWhen == TransitSectionAction.BLOCKENTRY) || (tWhen == TransitSectionAction.BLOCKEXIT)) { 2143 tWhenString = blockList.get(blockBox.getSelectedIndex()).getSystemName(); 2144 } 2145 return true; 2146 } 2147 2148 private boolean validateSensor(String sName, boolean when) { 2149 // check if anything entered 2150 if (sName.length() < 1) { 2151 // no sensor selected 2152 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("NoSensorError")), 2153 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2154 return false; 2155 } 2156 // get the sensor corresponding to this name 2157 Sensor s = InstanceManager.sensorManagerInstance().getSensor(sName); 2158 if (s == null) { 2159 // There is no sensor corresponding to this name 2160 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("SensorEntryError")), 2161 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2162 return false; 2163 } 2164 if (!sName.equals(s.getUserName())) { 2165 if (when) { 2166 tWhenString = sName; 2167 } else { 2168 tWhatString = sName; 2169 } 2170 } 2171 return true; 2172 } 2173 2174 private boolean validateSignal(String sName, boolean when) { 2175 // check if anything is selected 2176 if (sName.length() < 1) { 2177 // no signal selected 2178 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("NoSignalError")), 2179 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2180 return false; 2181 } 2182 // get the signalMast or signalHead corresponding to this name 2183 SignalMast sm = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(sName); 2184 SignalHead sh = null; 2185 if (sm == null) { 2186 sh = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(sName); 2187 } 2188 if (sm == null && sh == null) { 2189 // There is no signal corresponding to this name 2190 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("SignalEntryError")), 2191 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2192 return false; 2193 } 2194 return true; 2195 } 2196 2197 /** 2198 * Validate entered data for selected Action. Converted to use JSpinners 2199 * where applicable, 2017. 2200 * 2201 * @return true if data entered into field whatStringField is valid for selected Action type tWhat 2202 */ 2203 private boolean validateWhatData() { 2204 tWhat = getWhatMenuCode((String)whatBox.getSelectedItem()); 2205 tWhatData1 = 0; 2206 tWhatData2 = 0; 2207 tWhatString = ""; 2208 switch (tWhat) { 2209 case TransitSectionAction.SETMAXSPEED: 2210 case TransitSectionAction.SETCURRENTSPEED: 2211 case TransitSectionAction.RAMPTRAINSPEED: 2212 tWhatData1 = Math.round(100 * (float) whatPercentSpinner.getValue()); 2213 break; 2214 case TransitSectionAction.TOMANUALMODE: 2215 tWhatString=""; 2216 if (doneSensorComboBox.getSelectedIndex() >= 0) { // it's optional, so might be -1 2217 tWhatString = doneSensorComboBox.getSelectedItemSystemName(); // sensor system name 2218 } 2219 if (tWhatString.length() >= 1) { 2220 if (!validateSensor(tWhatString, false)) { 2221 tWhatString = ""; 2222 } 2223 } 2224 break; 2225 case TransitSectionAction.SETLIGHT: 2226 tWhatString = "On"; // NOI18N 2227 if (offButton.isSelected()) { 2228 tWhatString = "Off"; // NOI18N 2229 } 2230 break; 2231 case TransitSectionAction.STARTBELL: 2232 case TransitSectionAction.STOPBELL: 2233 case TransitSectionAction.TERMINATETRAIN: 2234 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2235 break; 2236 case TransitSectionAction.LOADTRAININFO: 2237 if (trainInfoComboBox.getSelectedIndex() < 0 ) { 2238 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingTrainInfoFile")), 2239 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2240 return false; 2241 } 2242 tWhatString = (String)trainInfoComboBox.getSelectedItem(); 2243 if (locoAddressRoster.isSelected()) { 2244 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEROSTER; 2245 // the first item is "select..." 2246 if (rosterComboBox.getSelectedIndex() < 1) { 2247 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingRosterEntryOrLocoAddress")), 2248 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2249 return false; 2250 } 2251 tWhatString2 =((RosterEntry) rosterComboBox.getSelectedItem()).getId(); 2252 } else if (locoAddressNumber.isSelected()) { 2253 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPENUMBER; 2254 tWhatString2 = locoAddress.getText(); 2255 if ((tWhatString2 == null) || tWhatString2.isEmpty() || (tWhatString2.length() < 1)) { 2256 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingRosterEntryOrLocoAddress")), 2257 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2258 return false; 2259 } 2260 } else if (locoAddressDefault.isSelected()) { 2261 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEDEFAULT; 2262 tWhatString2 = ""; 2263 } else if (locoAddressCurrent.isSelected()) { 2264 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPECURRENT; 2265 tWhatString2 = ""; 2266 } else { 2267 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("UnKnownlocoaddresstype")), 2268 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2269 return false; 2270 } 2271 break; 2272 case TransitSectionAction.PAUSE: 2273 case TransitSectionAction.SOUNDHORN: 2274 tWhatData1 = (Integer) whatMinuteSpinner1.getValue(); 2275 break; 2276 case TransitSectionAction.SOUNDHORNPATTERN: 2277 tWhatData1 = (Integer) whatMinuteSpinner1.getValue(); 2278 tWhatData2 = (Integer) whatMinuteSpinner2.getValue(); 2279 tWhatString = whatStringField.getText(); 2280 if ((tWhatString == null) || tWhatString.isEmpty() || (tWhatString.length() < 1)) { 2281 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingPattern")), 2282 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2283 return false; 2284 } 2285 tWhatString = tWhatString.trim().toLowerCase(); 2286 for (int i = 0; i < tWhatString.length(); i++) { 2287 char c = tWhatString.charAt(i); 2288 if ((c != 's') && (c != 'l')) { 2289 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("ErrorPattern")), 2290 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2291 return false; 2292 } 2293 } 2294 whatStringField.setText(tWhatString); // re-enter normalized value in display field 2295 break; 2296 case TransitSectionAction.LOCOFUNCTION: 2297 tWhatData1 = (Integer) locoFunctionSpinner.getValue(); 2298 tWhatString = "On"; // NOI18N 2299 if (offButton.isSelected()) { 2300 tWhatString = "Off"; // NOI18N 2301 } 2302 break; 2303 case TransitSectionAction.SETSENSORACTIVE: 2304 case TransitSectionAction.SETSENSORINACTIVE: 2305 if (doneSensorComboBox.getSelectedIndex() > 0) { 2306 tWhatString = doneSensorComboBox.getSelectedItemSystemName(); 2307 } 2308 if (!validateSensor(tWhatString, false)) { 2309 return false; 2310 } 2311 break; 2312 case TransitSectionAction.HOLDSIGNAL: 2313 case TransitSectionAction.RELEASESIGNAL: 2314 if (signalMastComboBox.getSelectedIndex() > 0) { 2315 tWhatString = signalMastComboBox.getSelectedItemSystemName(); 2316 } else if (signalHeadComboBox.getSelectedIndex() > 0) { 2317 tWhatString = signalHeadComboBox.getSelectedItemSystemName(); 2318 } 2319 if (!validateSignal(tWhatString, false)) { 2320 return false; 2321 } 2322 break; 2323 case TransitSectionAction.PRESTARTRESUME: 2324 break; 2325 default: 2326 log.warn("Unhandled transit section action code: {}", tWhat); 2327 break; 2328 } 2329 return true; 2330 } 2331 2332 // initialize combos for add/edit action window 2333 private void initializeWhenBox() { 2334 whenBox.removeAllItems(); 2335 for (int i = 0; i <= TransitSectionAction.NUM_WHENS; i++) { 2336 whenBox.addItem(getWhenMenuText(i)); 2337 } 2338 } 2339 2340 private String getWhenMenuText(int i) { 2341 switch (i) { 2342 case TransitSectionAction.ENTRY: 2343 return rbx.getString("OnEntry"); 2344 case TransitSectionAction.EXIT: 2345 return rbx.getString("OnExit"); 2346 case TransitSectionAction.BLOCKENTRY: 2347 return rbx.getString("OnBlockEntry"); 2348 case TransitSectionAction.BLOCKEXIT: 2349 return rbx.getString("OnBlockExit"); 2350 case TransitSectionAction.TRAINSTOP: 2351 return rbx.getString("TrainStop"); 2352 case TransitSectionAction.TRAINSTART: 2353 return rbx.getString("TrainStart"); 2354 case TransitSectionAction.SENSORACTIVE: 2355 return rbx.getString("OnSensorActive"); 2356 case TransitSectionAction.SENSORINACTIVE: 2357 return rbx.getString("OnSensorInactive"); 2358 case TransitSectionAction.PRESTARTDELAY: 2359 return rbx.getString("PreStartDelay"); 2360 case TransitSectionAction.PRESTARTACTION: 2361 return rbx.getString("PreStartAction"); 2362 case TransitSectionAction.SELECTWHEN: 2363 return rbx.getString("SelectWhen"); 2364 default: 2365 log.warn("Unhandled transit section when code: {}", i); 2366 return rbx.getString("SelectWhen"); 2367 } 2368 } 2369 2370 private int getWhenMenuCode(String s) { 2371 if (s.equals(rbx.getString("OnEntry"))) { 2372 return TransitSectionAction.ENTRY; 2373 } 2374 if (s.equals(rbx.getString("OnExit"))) { 2375 return TransitSectionAction.EXIT; 2376 } 2377 if (s.equals(rbx.getString("OnBlockEntry"))) { 2378 return TransitSectionAction.BLOCKENTRY; 2379 } 2380 if (s.equals(rbx.getString("OnBlockExit"))) { 2381 return TransitSectionAction.BLOCKEXIT; 2382 } 2383 if (s.equals(rbx.getString("TrainStop"))) { 2384 return TransitSectionAction.TRAINSTOP; 2385 } 2386 if (s.equals(rbx.getString("TrainStart"))) { 2387 return TransitSectionAction.TRAINSTART; 2388 } 2389 if (s.equals(rbx.getString("OnSensorActive"))) { 2390 return TransitSectionAction.SENSORACTIVE; 2391 } 2392 if (s.equals(rbx.getString("OnSensorInactive"))) { 2393 return TransitSectionAction.SENSORINACTIVE; 2394 } 2395 if (s.equals(rbx.getString("PreStartDelay"))) { 2396 return TransitSectionAction.PRESTARTDELAY; 2397 } 2398 if (s.equals(rbx.getString("PreStartAction"))) { 2399 return TransitSectionAction.PRESTARTACTION; 2400 } 2401 return TransitSectionAction.SELECTWHEN; 2402 } 2403 2404 private void initializeWhatBox(int code) { 2405 whatBox.removeAllItems(); 2406 List<Integer> excludeCodes = new ArrayList<>(); 2407 List<Integer> includeCodes = new ArrayList<>(); 2408 if (code == TransitSectionAction.PRESTARTACTION) { 2409 // exclude speed changing as that messes up the prestart.List<Section> sectionList = new ArrayList<>(); 2410 excludeCodes = new ArrayList<>(Arrays.asList(TransitSectionAction.SETMAXSPEED, TransitSectionAction.SETCURRENTSPEED, 2411 TransitSectionAction.RAMPTRAINSPEED)); 2412 } else if (code == TransitSectionAction.PRESTARTDELAY) { 2413 includeCodes.add(TransitSectionAction.PRESTARTRESUME); 2414 } else { 2415 excludeCodes.add(TransitSectionAction.PRESTARTRESUME); 2416 } 2417 for (int i = 0; i <= TransitSectionAction.NUM_WHATS; i++) { 2418 if (!excludeCodes.isEmpty()) { 2419 if (! excludeCodes.contains(i)) { 2420 whatBox.addItem(getWhatMenuText(i)); 2421 } 2422 } else if (!includeCodes.isEmpty()) { 2423 if (includeCodes.contains(i)) { 2424 whatBox.addItem(getWhatMenuText(i)); 2425 } 2426 } else { 2427 whatBox.addItem(getWhatMenuText(i)); 2428 } 2429 } 2430 } 2431 2432 @Nonnull 2433 private String getWhatMenuText(int i) { 2434 switch (i) { 2435 case TransitSectionAction.SELECTWHAT: 2436 return rbx.getString("SelectWhat"); 2437 case TransitSectionAction.TERMINATETRAIN: 2438 return rbx.getString("TerminateTrain"); 2439 case TransitSectionAction.LOADTRAININFO: 2440 return rbx.getString("LoadTrainInfo"); 2441 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2442 return rbx.getString("ForcePassNextSafe"); 2443 case TransitSectionAction.PAUSE: 2444 return rbx.getString("Pause"); 2445 case TransitSectionAction.SETMAXSPEED: 2446 return rbx.getString("SetMaxSpeed"); 2447 case TransitSectionAction.SETCURRENTSPEED: 2448 return rbx.getString("SetTrainSpeed"); 2449 case TransitSectionAction.RAMPTRAINSPEED: 2450 return rbx.getString("RampTrainSpeed"); 2451 case TransitSectionAction.TOMANUALMODE: 2452 return rbx.getString("ToManualMode"); 2453 case TransitSectionAction.SETLIGHT: 2454 return rbx.getString("SetLight"); 2455 case TransitSectionAction.STARTBELL: 2456 return rbx.getString("StartBell"); 2457 case TransitSectionAction.STOPBELL: 2458 return rbx.getString("StopBell"); 2459 case TransitSectionAction.SOUNDHORN: 2460 return rbx.getString("SoundHorn"); 2461 case TransitSectionAction.SOUNDHORNPATTERN: 2462 return rbx.getString("SoundHornPattern"); 2463 case TransitSectionAction.LOCOFUNCTION: 2464 return rbx.getString("LocoFunction"); 2465 case TransitSectionAction.SETSENSORACTIVE: 2466 return rbx.getString("SetSensorActive"); 2467 case TransitSectionAction.SETSENSORINACTIVE: 2468 return rbx.getString("SetSensorInactive"); 2469 case TransitSectionAction.HOLDSIGNAL: 2470 return rbx.getString("HoldSignal"); 2471 case TransitSectionAction.RELEASESIGNAL: 2472 return rbx.getString("ReleaseSignal"); 2473 case TransitSectionAction.ESTOP: 2474 return rbx.getString("EStop"); 2475 case TransitSectionAction.PRESTARTRESUME: 2476 return rbx.getString("PreStartResume"); 2477 default: 2478 log.warn("Unhandled transit section action code: {}", i); 2479 return rbx.getString("SelectWhat"); 2480 } 2481 } 2482 2483 private int getWhatMenuCode(@Nonnull String s) { 2484 if (s.equals(rbx.getString("SelectWhat"))) { 2485 return TransitSectionAction.SELECTWHAT; 2486 } 2487 if (s.equals(rbx.getString("TerminateTrain"))) { 2488 return TransitSectionAction.TERMINATETRAIN; 2489 } 2490 if (s.equals(rbx.getString("ForcePassNextSafe"))) { 2491 return TransitSectionAction.FORCEALLOCATEPASSSAFESECTION; 2492 } 2493 if (s.equals(rbx.getString("LoadTrainInfo"))) { 2494 return TransitSectionAction.LOADTRAININFO; 2495 } 2496 if (s.equals(rbx.getString("Pause"))) { 2497 return TransitSectionAction.PAUSE; 2498 } 2499 if (s.equals(rbx.getString("SetMaxSpeed"))) { 2500 return TransitSectionAction.SETMAXSPEED; 2501 } 2502 if (s.equals(rbx.getString("SetTrainSpeed"))) { 2503 return TransitSectionAction.SETCURRENTSPEED; 2504 } 2505 if (s.equals(rbx.getString("RampTrainSpeed"))) { 2506 return TransitSectionAction.RAMPTRAINSPEED; 2507 } 2508 if (s.equals(rbx.getString("ToManualMode"))) { 2509 return TransitSectionAction.TOMANUALMODE; 2510 } 2511 if (s.equals(rbx.getString("SetLight"))) { 2512 return TransitSectionAction.SETLIGHT; 2513 } 2514 if (s.equals(rbx.getString("StartBell"))) { 2515 return TransitSectionAction.STARTBELL; 2516 } 2517 if (s.equals(rbx.getString("StopBell"))) { 2518 return TransitSectionAction.STOPBELL; 2519 } 2520 if (s.equals(rbx.getString("SoundHorn"))) { 2521 return TransitSectionAction.SOUNDHORN; 2522 } 2523 if (s.equals(rbx.getString("SoundHornPattern"))) { 2524 return TransitSectionAction.SOUNDHORNPATTERN; 2525 } 2526 if (s.equals(rbx.getString("LocoFunction"))) { 2527 return TransitSectionAction.LOCOFUNCTION; 2528 } 2529 if (s.equals(rbx.getString("SetSensorActive"))) { 2530 return TransitSectionAction.SETSENSORACTIVE; 2531 } 2532 if (s.equals(rbx.getString("SetSensorInactive"))) { 2533 return TransitSectionAction.SETSENSORINACTIVE; 2534 } 2535 if (s.equals(rbx.getString("HoldSignal"))) { 2536 return TransitSectionAction.HOLDSIGNAL; 2537 } 2538 if (s.equals(rbx.getString("ReleaseSignal"))) { 2539 return TransitSectionAction.RELEASESIGNAL; 2540 } 2541 if (s.equals(rbx.getString("EStop"))) { 2542 return TransitSectionAction.ESTOP; 2543 } 2544 if (s.equals(rbx.getString("PreStartResume"))) { 2545 return TransitSectionAction.PRESTARTRESUME; 2546 } 2547 log.warn("Unhandled transit section action text: {}", s); 2548 return 0; 2549 } 2550 2551 private void initializeBlockBox() { 2552 blockList = sectionList.get(activeRow).getBlockList(); 2553 blockBox.removeAllItems(); 2554 for (int i = 0; i < blockList.size(); i++) { 2555 String s = blockList.get(i).getDisplayName(); 2556 blockBox.addItem(s); 2557 } 2558 } 2559 2560 private void setBlockBox() { 2561 if (editActionMode) { 2562 if ((curTSA.getWhenCode() == TransitSectionAction.BLOCKENTRY) 2563 || (curTSA.getWhenCode() == TransitSectionAction.BLOCKEXIT)) { 2564 // assumes that initializeBlockBox has been called prior to this call 2565 for (int i = 0; i < blockList.size(); i++) { 2566 if (curTSA.getStringWhen().equals(blockList.get(i).getSystemName())) { 2567 blockBox.setSelectedIndex(i); 2568 return; 2569 } 2570 } 2571 } 2572 } 2573 blockBox.setSelectedIndex(0); 2574 } 2575 2576 private void editAction(int r) { 2577 curTSA = action.get(activeRow).get(r); 2578 editActionMode = true; 2579 addEditActionWindow(); 2580 } 2581 2582 private void deleteAction(int r) { 2583 TransitSectionAction tsa = action.get(activeRow).get(r); 2584 action.get(activeRow).remove(r); 2585 tsa.dispose(); 2586 actionTableModel.fireTableDataChanged(); 2587 } 2588 2589 /** 2590 * Build display When string for Actions table. 2591 * 2592 * @param r row in the Special Actions table. A TransitSectionAction must be 2593 * available for this row. 2594 * @return display string including entered values 2595 */ 2596 private String getWhenText(int r) { 2597 TransitSectionAction tsa = action.get(activeRow).get(r); 2598 switch (tsa.getWhenCode()) { 2599 case TransitSectionAction.ENTRY: 2600 if (tsa.getDataWhen() > 0) { 2601 return java.text.MessageFormat.format(rbx.getString("OnEntryDelayedFull"), 2602 new Object[]{"" + tsa.getDataWhen()}); 2603 } 2604 return rbx.getString("OnEntryFull"); 2605 case TransitSectionAction.EXIT: 2606 if (tsa.getDataWhen() > 0) { 2607 return java.text.MessageFormat.format(rbx.getString("OnExitDelayedFull"), 2608 new Object[]{"" + tsa.getDataWhen()}); 2609 } 2610 return rbx.getString("OnExitFull"); 2611 case TransitSectionAction.BLOCKENTRY: 2612 if (tsa.getDataWhen() > 0) { 2613 return java.text.MessageFormat.format(rbx.getString("OnBlockEntryDelayedFull"), 2614 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2615 } 2616 return java.text.MessageFormat.format(rbx.getString("OnBlockEntryFull"), 2617 new Object[]{tsa.getStringWhen()}); 2618 case TransitSectionAction.BLOCKEXIT: 2619 if (tsa.getDataWhen() > 0) { 2620 return java.text.MessageFormat.format(rbx.getString("OnBlockExitDelayedFull"), 2621 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2622 } 2623 return java.text.MessageFormat.format(rbx.getString("OnBlockExitFull"), 2624 new Object[]{tsa.getStringWhen()}); 2625 case TransitSectionAction.TRAINSTOP: 2626 if (tsa.getDataWhen() > 0) { 2627 return java.text.MessageFormat.format(rbx.getString("TrainStopDelayedFull"), 2628 new Object[]{"" + tsa.getDataWhen()}); 2629 } 2630 return rbx.getString("TrainStopFull"); 2631 case TransitSectionAction.TRAINSTART: 2632 if (tsa.getDataWhen() > 0) { 2633 return java.text.MessageFormat.format(rbx.getString("TrainStartDelayedFull"), 2634 new Object[]{"" + tsa.getDataWhen()}); 2635 } 2636 return rbx.getString("TrainStartFull"); 2637 case TransitSectionAction.SENSORACTIVE: 2638 if (tsa.getDataWhen() > 0) { 2639 return java.text.MessageFormat.format(rbx.getString("OnSensorActiveDelayedFull"), 2640 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2641 } 2642 return java.text.MessageFormat.format(rbx.getString("OnSensorActiveFull"), 2643 new Object[]{tsa.getStringWhen()}); 2644 case TransitSectionAction.SENSORINACTIVE: 2645 if (tsa.getDataWhen() > 0) { 2646 return java.text.MessageFormat.format(rbx.getString("OnSensorInactiveDelayedFull"), 2647 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2648 } 2649 return java.text.MessageFormat.format(rbx.getString("OnSensorInactiveFull"), 2650 new Object[]{tsa.getStringWhen()}); 2651 case TransitSectionAction.PRESTARTDELAY: 2652 return java.text.MessageFormat.format(rbx.getString("PreStartDelayFull"), 2653 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2654 case TransitSectionAction.PRESTARTACTION: 2655 return java.text.MessageFormat.format(rbx.getString("PreStartActionFull"), 2656 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2657 default: 2658 log.warn("Unhandled transit section action When code: {}",tsa.getWhenCode()); 2659 return(""); 2660 } 2661 } 2662 2663 /** 2664 * Build display What string for Actions table. 2665 * 2666 * @param r row in the Special Actions table. A TransitSectionAction must be 2667 * available for this row. 2668 * @return display string including entered values 2669 */ 2670 private String getWhatText(int r) { 2671 TransitSectionAction tsa = action.get(activeRow).get(r); 2672 switch (tsa.getWhatCode()) { 2673 case TransitSectionAction.PAUSE: 2674 return java.text.MessageFormat.format(rbx.getString("PauseFull"), 2675 new Object[]{tsa.getDataWhat1()}); 2676 case TransitSectionAction.SETMAXSPEED: 2677 return java.text.MessageFormat.format(rbx.getString("SetMaxSpeedFull"), 2678 new Object[]{tsa.getDataWhat1()}); 2679 case TransitSectionAction.SETCURRENTSPEED: 2680 return java.text.MessageFormat.format(rbx.getString("SetTrainSpeedFull"), 2681 new Object[]{tsa.getDataWhat1()}); 2682 case TransitSectionAction.RAMPTRAINSPEED: 2683 return java.text.MessageFormat.format(rbx.getString("RampTrainSpeedFull"), 2684 new Object[]{"" + tsa.getDataWhat1()}); 2685 case TransitSectionAction.TOMANUALMODE: 2686 if (tsa.getStringWhat().length() > 0) { 2687 return java.text.MessageFormat.format(rbx.getString("ToManualModeAltFull"), 2688 new Object[]{tsa.getStringWhat()}); 2689 } 2690 return rbx.getString("ToManualModeFull"); 2691 case TransitSectionAction.SETLIGHT: 2692 if (tsa.getStringWhat().equals("Off")) { 2693 return java.text.MessageFormat.format(rbx.getString("SetLightFull"), 2694 new Object[]{Bundle.getMessage("StateOff")}); 2695 } 2696 return java.text.MessageFormat.format(rbx.getString("SetLightFull"), 2697 new Object[]{Bundle.getMessage("StateOn")}); 2698 case TransitSectionAction.STARTBELL: 2699 return rbx.getString("StartBellFull"); 2700 case TransitSectionAction.STOPBELL: 2701 return rbx.getString("StopBellFull"); 2702 case TransitSectionAction.SOUNDHORN: 2703 return java.text.MessageFormat.format(rbx.getString("SoundHornFull"), 2704 new Object[]{tsa.getDataWhat1()}); 2705 case TransitSectionAction.SOUNDHORNPATTERN: 2706 return java.text.MessageFormat.format(rbx.getString("SoundHornPatternFull"), 2707 new Object[]{tsa.getStringWhat(), "" + tsa.getDataWhat1(), "" + tsa.getDataWhat2()}); 2708 case TransitSectionAction.LOCOFUNCTION: 2709 if (tsa.getStringWhat().equals("Off")) { 2710 return java.text.MessageFormat.format(rbx.getString("LocoFunctionFull"), 2711 new Object[]{"" + tsa.getDataWhat1(), Bundle.getMessage("StateOff")}); 2712 } 2713 return java.text.MessageFormat.format(rbx.getString("LocoFunctionFull"), 2714 new Object[]{"" + tsa.getDataWhat1(), Bundle.getMessage("StateOn")}); 2715 case TransitSectionAction.SETSENSORACTIVE: 2716 return java.text.MessageFormat.format(rbx.getString("SetSensorActiveFull"), 2717 new Object[]{tsa.getStringWhat()}); 2718 case TransitSectionAction.SETSENSORINACTIVE: 2719 return java.text.MessageFormat.format(rbx.getString("SetSensorInactiveFull"), 2720 new Object[]{tsa.getStringWhat()}); 2721 case TransitSectionAction.HOLDSIGNAL: 2722 return java.text.MessageFormat.format(rbx.getString("HoldSignalFull"), 2723 new Object[]{tsa.getStringWhat()}); 2724 case TransitSectionAction.RELEASESIGNAL: 2725 return java.text.MessageFormat.format(rbx.getString("ReleaseSignalFull"), 2726 new Object[]{tsa.getStringWhat()}); 2727 case TransitSectionAction.PRESTARTRESUME: 2728 return java.text.MessageFormat.format(rbx.getString("PreStartResumeFull"), 2729 new Object[]{tsa.getDataWhen()}); 2730 case TransitSectionAction.ESTOP: 2731 return rbx.getString("EStopFull"); 2732 case TransitSectionAction.TERMINATETRAIN: 2733 return rbx.getString("TerminateTrain"); 2734 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2735 return rbx.getString("ForcePassNextSafe"); 2736 case TransitSectionAction.LOADTRAININFO: 2737 switch (tsa.getDataWhat2()) { 2738 case TransitSectionAction.LOCOADDRESSTYPEROSTER: 2739 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoRosterFull"), 2740 new Object[]{tsa.getStringWhat(),tsa.getStringWhat2()}); 2741 case TransitSectionAction.LOCOADDRESSTYPENUMBER: 2742 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoNumberFull"), 2743 new Object[]{tsa.getStringWhat(),tsa.getStringWhat2()}); 2744 case TransitSectionAction.LOCOADDRESSTYPECURRENT: 2745 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoCurrentFull"), 2746 new Object[]{tsa.getStringWhat()}); 2747 case TransitSectionAction.LOCOADDRESSTYPEDEFAULT: 2748 default: 2749 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoDefaultFull"), 2750 new Object[]{tsa.getStringWhat()}); 2751 } 2752 case TransitSectionAction.SELECTWHAT: 2753 return rbx.getString("SelectWhat"); 2754 default: 2755 log.warn("Unhandled transit section action What code: {}", tsa.getWhatCode()); 2756 break; 2757 } 2758 return "WHAT"; 2759 } 2760 2761 private String getSectionNameByRow(int r) { 2762 return sectionList.get(r).getDisplayName(); 2763 } 2764 2765 /** 2766 * Table model for Sections in Create/Edit Transit window. 2767 */ 2768 public class SectionTableModel extends javax.swing.table.AbstractTableModel implements 2769 java.beans.PropertyChangeListener { 2770 2771 public static final int SEQUENCE_COLUMN = 0; 2772 public static final int SECTIONNAME_COLUMN = 1; 2773 public static final int ACTION_COLUMN = 2; 2774 public static final int SEC_DIRECTION_COLUMN = 3; 2775 public static final int ALTERNATE_COLUMN = 4; 2776 public static final int SAFE_COLUMN = 5; 2777 public static final int STOPALLOCATING_SENSOR = 6; 2778 public static final int FWD_STOPPING_LENGTH = 7; 2779 public static final int REV_STOPPING_LENGTH = 8; 2780 public static final int NUMBER_OF_COLUMNS = 9; 2781 2782 public SectionTableModel() { 2783 super(); 2784 addPcl(); 2785 } 2786 2787 final void addPcl(){ 2788 sectionManager.addPropertyChangeListener(this); 2789 } 2790 2791 @Override 2792 public void propertyChange(java.beans.PropertyChangeEvent e) { 2793 if (Manager.PROPERTY_LENGTH.equals(e.getPropertyName())) { 2794 // a new NamedBean is available in the manager 2795 fireTableDataChanged(); 2796 } 2797 if (e.getSource() instanceof SensorManager 2798 && SensorManager.PROPERTY_DISPLAY_LIST_NAME.equals(e.getPropertyName())) { 2799 updateSensorList(); 2800 } 2801 } 2802 2803 @Override 2804 public Class<?> getColumnClass(int c) { 2805 switch (c) { 2806 case ACTION_COLUMN: 2807 return JButton.class; 2808 case SAFE_COLUMN: 2809 return Boolean.class; 2810 case STOPALLOCATING_SENSOR: 2811 return JComboBox.class; 2812 case FWD_STOPPING_LENGTH: 2813 case REV_STOPPING_LENGTH: 2814 return JSpinner.class; 2815 default: 2816 return super.getColumnClass(c); 2817 } 2818 } 2819 2820 @Override 2821 public int getColumnCount() { 2822 return NUMBER_OF_COLUMNS; 2823 } 2824 2825 @Override 2826 public int getRowCount() { 2827 return (sectionList.size()); 2828 } 2829 2830 @Override 2831 public boolean isCellEditable(int r, int c) { 2832 switch (c) { 2833 case ACTION_COLUMN: 2834 case SAFE_COLUMN: 2835 case STOPALLOCATING_SENSOR: 2836 case FWD_STOPPING_LENGTH: 2837 case REV_STOPPING_LENGTH: 2838 return true; 2839 default: 2840 return false; 2841 } 2842 } 2843 2844 @Override 2845 public String getColumnName(int col) { 2846 switch (col) { 2847 case SEQUENCE_COLUMN: 2848 return rbx.getString("SequenceColName"); 2849 case SECTIONNAME_COLUMN: 2850 return Bundle.getMessage("BeanNameSection"); 2851 case ACTION_COLUMN: 2852 return rbx.getString("ActionColName"); 2853 case SEC_DIRECTION_COLUMN: 2854 return rbx.getString("DirectionColName"); 2855 case ALTERNATE_COLUMN: 2856 return rbx.getString("AlternateColName"); 2857 case SAFE_COLUMN: 2858 return rbx.getString("SafeColName"); 2859 case STOPALLOCATING_SENSOR: 2860 return rbx.getString("StopAllocationColName"); 2861 case FWD_STOPPING_LENGTH: 2862 return rbx.getString("FwdStopDistance"); 2863 case REV_STOPPING_LENGTH: 2864 return rbx.getString("RevStopDistance"); 2865 default: 2866 return ""; 2867 } 2868 } 2869 2870 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", 2871 justification="better to keep cases in column order rather than to combine") 2872 public int getPreferredWidth(int col) { 2873 switch (col) { 2874 case SEQUENCE_COLUMN: 2875 return new JTextField(8).getPreferredSize().width; 2876 case SECTIONNAME_COLUMN: 2877 return new JTextField(17).getPreferredSize().width; 2878 case ACTION_COLUMN: 2879 return new JTextField(12).getPreferredSize().width; 2880 case SEC_DIRECTION_COLUMN: 2881 return new JTextField(12).getPreferredSize().width; 2882 case ALTERNATE_COLUMN: 2883 return new JTextField(12).getPreferredSize().width; 2884 case SAFE_COLUMN: 2885 return new JTextField(4).getPreferredSize().width; 2886 case STOPALLOCATING_SENSOR: 2887 return new JTextField(12).getPreferredSize().width; 2888 case FWD_STOPPING_LENGTH: 2889 return new JTextField(12).getPreferredSize().width; 2890 case REV_STOPPING_LENGTH: 2891 return new JTextField(12).getPreferredSize().width; 2892 default: 2893 // fall through 2894 break; 2895 } 2896 return new JTextField(5).getPreferredSize().width; 2897 } 2898 2899 @Override 2900 public Object getValueAt(int r, int c) { 2901 int rx = r; 2902 if (rx > sectionList.size()) { 2903 return null; 2904 } 2905 switch (c) { 2906 case SEQUENCE_COLUMN: 2907 return ("" + sequence.get(rx)); 2908 case SECTIONNAME_COLUMN: 2909 return (getSectionNameByRow(rx)); 2910 case ACTION_COLUMN: 2911 return rbx.getString("AddEditActions"); 2912 case SEC_DIRECTION_COLUMN: 2913 if (direction.get(rx) == Section.FORWARD) { 2914 return rbx.getString("SectionForward"); 2915 } else if (direction.get(rx) == Section.REVERSE) { 2916 return rbx.getString("SectionReverse"); 2917 } 2918 return Bundle.getMessage("BeanStateUnknown"); 2919 case ALTERNATE_COLUMN: 2920 if (alternate.get(rx)) { 2921 return rbx.getString("Alternate"); 2922 } 2923 return rbx.getString("Primary"); 2924 case SAFE_COLUMN: 2925 return safe.get(rx); 2926 case STOPALLOCATING_SENSOR: 2927 String sensor = sensorStopAllocation.get(rx); 2928 JComboBox<String> cb = new JComboBox<>(sensorList); 2929 JComboBoxUtil.setupComboBoxMaxRows(cb); 2930 String name = (sensor != null) ? sensor : ""; 2931 cb.setSelectedItem(name); 2932 return cb; 2933 case FWD_STOPPING_LENGTH: 2934 JSpinner jf = new JSpinner(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.0f), Float.valueOf(2.0f), Float.valueOf(0.05f))); 2935 jf.setEditor(new JSpinner.NumberEditor(jf, "##0.0# %")); 2936 jf.setValue(fwdStopPerCent.get(rx)); 2937 return jf; 2938 case REV_STOPPING_LENGTH: 2939 JSpinner jr = new JSpinner(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.0f), Float.valueOf(2.0f), Float.valueOf(0.05f))); 2940 jr.setEditor(new JSpinner.NumberEditor(jr, "##0.0# %")); 2941 jr.setValue(revStopPerCent.get(rx)); 2942 return jr; 2943 default: 2944 return Bundle.getMessage("BeanStateUnknown"); 2945 } 2946 } 2947 2948 @Override 2949 public void setValueAt(Object value, int row, int col) { 2950 switch (col) { 2951 case ACTION_COLUMN: 2952 addEditActionsPressed(row); 2953 break; 2954 case SAFE_COLUMN: 2955 boolean val = ((Boolean) value); 2956 safe.set(row, val); // use checkbox to show Safe 2957 break; 2958 case STOPALLOCATING_SENSOR: 2959 JComboBox<?> cb = (JComboBox<?>) value; 2960 if (cb.getSelectedIndex() < 0) { 2961 sensorStopAllocation.set(row, ""); 2962 } else { 2963 sensorStopAllocation.set(row, (String) cb.getSelectedItem()); 2964 } 2965 break; 2966 case FWD_STOPPING_LENGTH: 2967 fwdStopPerCent.set(row, (Float)value); 2968 break; 2969 case REV_STOPPING_LENGTH: 2970 revStopPerCent.set(row, (Float)value); 2971 break; 2972 default: 2973 break; 2974 } 2975 } 2976 2977 public void dispose(){ 2978 sectionManager.removePropertyChangeListener(this); 2979 } 2980 } 2981 2982 private void updateSensorList() { 2983 Set<Sensor> nameSet = InstanceManager.getDefault(SensorManager.class).getNamedBeanSet(); 2984 String[] displayList = new String[nameSet.size()]; 2985 int i = 0; 2986 for (Sensor nBean : nameSet) { 2987 if (nBean != null) { 2988 displayList[i++] = nBean.getDisplayName(); 2989 } 2990 } 2991 java.util.Arrays.sort(displayList, new jmri.util.AlphanumComparator()); 2992 sensorList = new String[displayList.length + 1]; 2993 sensorList[0] = ""; 2994 i = 1; 2995 for (String name : displayList) { 2996 sensorList[i] = name; 2997 i++; 2998 } 2999 } 3000 3001 3002 /** 3003 * Table model for Actions in Special Actions window. Currently shows max. 5 3004 * rows. 3005 */ 3006 public class SpecialActionTableModel extends javax.swing.table.AbstractTableModel implements 3007 java.beans.PropertyChangeListener { 3008 3009 public static final int WHEN_COLUMN = 0; 3010 public static final int WHAT_COLUMN = 1; 3011 public static final int EDIT_COLUMN = 2; 3012 public static final int REMOVE_COLUMN = 3; 3013 3014 public SpecialActionTableModel() { 3015 super(); 3016 addPcl(); 3017 } 3018 3019 final void addPcl(){ 3020 sectionManager.addPropertyChangeListener(this); 3021 } 3022 3023 @Override 3024 public void propertyChange(java.beans.PropertyChangeEvent e) { 3025 if ( Manager.PROPERTY_LENGTH.equals(e.getPropertyName())) { 3026 // a new NamedBean is available in the manager 3027 fireTableDataChanged(); 3028 } 3029 } 3030 3031 @Override 3032 public Class<?> getColumnClass(int c) { 3033 switch (c) { 3034 case EDIT_COLUMN: 3035 case REMOVE_COLUMN: 3036 return JButton.class; 3037 case WHEN_COLUMN: 3038 case WHAT_COLUMN: 3039 default: 3040 return String.class; 3041 } 3042 } 3043 3044 @Override 3045 public int getColumnCount() { 3046 return REMOVE_COLUMN + 1; 3047 } 3048 3049 @Override 3050 public int getRowCount() { 3051 return (action.get(activeRow).size()); 3052 } 3053 3054 @Override 3055 public boolean isCellEditable(int r, int c) { 3056 switch (c) { 3057 case EDIT_COLUMN: 3058 case REMOVE_COLUMN: 3059 return true; 3060 default: 3061 return false; 3062 } 3063 } 3064 3065 @Override 3066 public String getColumnName(int col) { 3067 switch (col) { 3068 case WHEN_COLUMN: 3069 return rbx.getString("WhenColName"); 3070 case WHAT_COLUMN: 3071 return rbx.getString("WhatColName"); 3072 default: 3073 return ""; 3074 } 3075 } 3076 3077 public int getPreferredWidth(int col) { 3078 switch (col) { 3079 case WHEN_COLUMN: 3080 case WHAT_COLUMN: 3081 return new JTextField(50).getPreferredSize().width; 3082 case EDIT_COLUMN: 3083 case REMOVE_COLUMN: 3084 default: 3085 return new JTextField(8).getPreferredSize().width; 3086 } 3087 } 3088 3089 @Override 3090 public Object getValueAt(int r, int c) { 3091 int rx = r; 3092 if (rx > action.get(activeRow).size()) { 3093 return null; 3094 } 3095 switch (c) { 3096 case WHEN_COLUMN: 3097 return (getWhenText(rx)); 3098 case WHAT_COLUMN: 3099 return (getWhatText(rx)); 3100 case EDIT_COLUMN: 3101 return Bundle.getMessage("ButtonEdit"); 3102 case REMOVE_COLUMN: 3103 return Bundle.getMessage("ButtonDelete"); 3104 default: 3105 return Bundle.getMessage("BeanStateUnknown"); // normally not in use 3106 } 3107 } 3108 3109 @Override 3110 public void setValueAt(Object value, int row, int col) { 3111 if (col == EDIT_COLUMN) { 3112 // set up to edit 3113 editAction(row); 3114 } 3115 else if (col == REMOVE_COLUMN) { 3116 deleteAction(row); 3117 } 3118 } 3119 3120 public void dispose(){ 3121 sectionManager.removePropertyChangeListener(this); 3122 } 3123 } 3124 3125 @Override 3126 protected String getClassName() { 3127 return TransitTableAction.class.getName(); 3128 } 3129 3130 @Override 3131 public String getClassDescription() { 3132 return Bundle.getMessage("TitleTransitTable"); 3133 } 3134 3135 public class JSpinnerCellRenderer extends DefaultTableCellRenderer { 3136 3137 public JSpinnerCellRenderer() { 3138 } 3139 3140 @Override 3141 public Component getTableCellRendererComponent(JTable table, Object value, 3142 boolean isSelected, boolean hasFocus, 3143 int row, int column) { 3144 if (value instanceof JSpinner) { 3145 switch (column) { 3146 case SectionTableModel.FWD_STOPPING_LENGTH: 3147 ((JSpinner) value).setValue(fwdStopPerCent.get(row)); 3148 break; 3149 case SectionTableModel.REV_STOPPING_LENGTH: 3150 ((JSpinner) value).setValue(revStopPerCent.get(row)); 3151 break; 3152 default: 3153 log.error("getTableCellEditorComponent col[{}] is bad.",column); 3154 } 3155 } 3156 return (Component)value; 3157 } 3158 } 3159 3160 public class JSpinnerCellEditor extends AbstractCellEditor implements TableCellEditor { 3161 private JSpinner spinner; 3162 3163 public JSpinnerCellEditor() { 3164 } 3165 3166 @Override 3167 public Component getTableCellEditorComponent(JTable table, Object value, 3168 boolean isSelected, int row, int column) { 3169 spinner = (JSpinner) value; 3170 if (value instanceof JSpinner) { 3171 switch (column) { 3172 case SectionTableModel.FWD_STOPPING_LENGTH: 3173 ((JSpinner) value).setValue(fwdStopPerCent.get(row)); 3174 break; 3175 case SectionTableModel.REV_STOPPING_LENGTH: 3176 ((JSpinner) value).setValue(revStopPerCent.get(row)); 3177 break; 3178 default: 3179 log.error("getTableCellEditorComponent col[{}] is bad.",column); 3180 } 3181 } 3182 return (Component)value; 3183 } 3184 3185 @Override 3186 public Object getCellEditorValue() { 3187 return spinner.getValue(); 3188 } 3189 } 3190 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TransitTableAction.class); 3191 3192}