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 fwdStopPerCent.add(0, Float.valueOf(1.0f)); 695 revStopPerCent.add(0, Float.valueOf(1.0f)); 696 initializeSectionCombos(); 697 } 698 updateSeqNum(); 699 sectionTableModel.fireTableDataChanged(); 700 } 701 702 void removeLastSectionPressed(ActionEvent e) { 703 if (sectionList.size() <= 1) { 704 deleteAllSections(e); 705 } else { 706 int j = sectionList.size() - 1; 707 if (!alternate.get(j)) { 708 curSequenceNum--; 709 curSection = sectionList.get(j - 1); 710 curSectionDirection = direction.get(j - 1); 711 // delete alternate if present 712 int k = j - 2; 713 while ((k >= 0) && alternate.get(k)) { 714 k--; 715 } 716 // After this delete we need the new previous section, if there is one. 717 if (k < 0) { 718 // There is no previous section 719 prevSection = null; 720 } else { 721 prevSection = sectionList.get(k); 722 prevSectionDirection = direction.get(k); 723 } 724 } 725 removeSupportingArrayEntries(j); 726 initializeSectionCombos(); 727 } 728 updateSeqNum(); 729 sectionTableModel.fireTableDataChanged(); 730 } 731 732 void insertAtBeginningPressed(ActionEvent e) { 733 if (insertAtBeginningBoxList.isEmpty()) { 734 JmriJOptionPane.showMessageDialog(addFrame, rbx 735 .getString("Message35"), Bundle.getMessage("ErrorTitle"), 736 JmriJOptionPane.ERROR_MESSAGE); 737 return; 738 } 739 int index = insertAtBeginningBox.getSelectedIndex(); 740 Section s = insertAtBeginningBoxList.get(index); 741 if (s != null) { 742 sectionList.add(0, s); 743 direction.add(0, insertAtBeginningDirection.get(index)); 744 curSequenceNum++; 745 sequence.add(0, 1); 746 alternate.add(0, false); 747 safe.add(0, addAsSafe.isSelected()); 748 sensorStopAllocation.add(0, ""); 749 action.add(0, new ArrayList<>()); 750 fwdStopPerCent.add(0, Float.valueOf(1.0f)); 751 revStopPerCent.add(0, Float.valueOf(1.0f)); 752 if (curSequenceNum == 2) { 753 prevSectionDirection = direction.get(0); 754 prevSection = s; 755 } 756 initializeSectionCombos(); 757 } 758 updateSeqNum(); 759 sectionTableModel.fireTableDataChanged(); 760 } 761 762 void removeFirstSectionPressed(ActionEvent e) { 763 if (curSequenceNum <= 1) { 764 deleteAllSections(e); 765 } else { 766 // For alternates we delete all 767 int keep = 1; 768 while (alternate.get(keep)) { 769 keep++; 770 } 771 for (int c = 0; c < keep ; c++) { 772 removeSupportingArrayEntries(0); 773 curSequenceNum--; 774 } 775 initializeSectionCombos(); 776 } 777 updateSeqNum(); 778 sectionTableModel.fireTableDataChanged(); 779 } 780 781 void replacePrimaryForSeqPressed(ActionEvent e) { 782 int seq = getSeqNum(); 783 if (seq == 0) { 784 return; 785 } 786 Section sOld = null; 787 List<Section> altOldList = new ArrayList<>(); 788 Section beforeSection = null; 789 int beforeSectionDirection = 0; 790 Section afterSection = null; 791 int afterSectionDirection = 0; 792 int index = -1; 793 for (int i = 0; i < sectionList.size(); i++) { 794 if ((sequence.get(i) == seq) && (!alternate.get(i))) { 795 sOld = sectionList.get(i); 796 index = i; 797 } 798 if ((sequence.get(i) == seq) && alternate.get(i)) { 799 altOldList.add(sectionList.get(i)); 800 } 801 if ((sequence.get(i) == (seq - 1)) && (!alternate.get(i))) { 802 beforeSection = sectionList.get(i); 803 beforeSectionDirection = direction.get(i); 804 } 805 if ((sequence.get(i) == (seq + 1)) && (!alternate.get(i))) { 806 afterSection = sectionList.get(i); 807 afterSectionDirection = Section.FORWARD; 808 if (afterSectionDirection == direction.get(i)) { 809 afterSectionDirection = Section.REVERSE; 810 } 811 } 812 } 813 if (sOld == null) { 814 log.error("Missing primary Section for seq = {}", seq); 815 return; 816 } 817 List<Section> possibles = new ArrayList<>(); 818 List<Integer> possiblesDirection = new ArrayList<>(); 819 List<String> possibleNames = new ArrayList<>(); 820 821 for (Section s : sectionManager.getNamedBeanSet()) { 822 Section mayBeSection = null; 823 String mayBeName = s.getDisplayName(); 824 int mayBeDirection = 0; 825 if ((s != sOld) && (s != beforeSection) 826 && (s != afterSection) && (!inSectionList(s, altOldList))) { 827 if (beforeSection != null) { 828 if (forwardConnected(s, beforeSection, beforeSectionDirection)) { 829 mayBeSection = s; 830 mayBeDirection = Section.FORWARD; 831 } else if (reverseConnected(s, beforeSection, beforeSectionDirection)) { 832 mayBeSection = s; 833 mayBeDirection = Section.REVERSE; 834 } 835 if ((mayBeSection != null) && (afterSection != null)) { 836 if (mayBeDirection == Section.REVERSE) { 837 if (!forwardConnected(s, afterSection, afterSectionDirection)) { 838 mayBeSection = null; 839 } 840 } else { 841 if (!reverseConnected(s, afterSection, afterSectionDirection)) { 842 mayBeSection = null; 843 } 844 } 845 } 846 } else if (afterSection != null) { 847 if (forwardConnected(s, afterSection, afterSectionDirection)) { 848 mayBeSection = s; 849 mayBeDirection = Section.REVERSE; 850 } else if (reverseConnected(s, afterSection, afterSectionDirection)) { 851 mayBeSection = s; 852 mayBeDirection = Section.FORWARD; 853 } 854 } else { 855 mayBeSection = s; 856 mayBeDirection = Section.FORWARD; 857 } 858 if (mayBeSection != null) { 859 possibles.add(mayBeSection); 860 possiblesDirection.add(mayBeDirection); 861 possibleNames.add(mayBeName); 862 } 863 } 864 } 865 if (possibles.isEmpty()) { 866 JmriJOptionPane.showMessageDialog(addFrame, 867 java.text.MessageFormat.format(rbx.getString("Message36"), 868 new Object[]{"" + seq}), Bundle.getMessage("ErrorTitle"), 869 JmriJOptionPane.ERROR_MESSAGE); 870 return; 871 } 872 int k = 0; 873 if (possibles.size() > 1) { 874 Object choices[] = new Object[possibles.size()]; 875 for (int j = 0; j < possibles.size(); j++) { 876 choices[j] = possibleNames.get(j); 877 } 878 Object selName = JmriJOptionPane.showInputDialog(addFrame, 879 rbx.getString("ReplacePrimaryChoice"), 880 rbx.getString("ReplacePrimaryTitle"), 881 JmriJOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 882 if (selName == null) { 883 return; 884 } 885 for (int j = 0; j < possibles.size(); j++) { 886 if (selName.equals(choices[j])) { 887 k = j; 888 } 889 } 890 } 891 sectionList.remove(index); 892 sectionList.add(index, possibles.get(k)); 893 direction.set(index, possiblesDirection.get(k)); 894 if (index == (sectionList.size() - 1)) { 895 curSection = sectionList.get(index); 896 curSectionDirection = direction.get(index); 897 } else if (index == (sectionList.size() - 2)) { 898 prevSection = sectionList.get(index); 899 prevSectionDirection = direction.get(index); 900 } 901 initializeSectionCombos(); 902 sectionTableModel.fireTableDataChanged(); 903 } 904 905 boolean inSectionList(Section s, List<Section> sList) { 906 for (int i = 0; i < sList.size(); i++) { 907 if (sList.get(i) == s) { 908 return true; 909 } 910 } 911 return false; 912 } 913 914 private int getSeqNum() { 915 int n = (Integer) seqNum.getValue(); // JSpinner int from 1 - sectionList.size() 916 if (n > curSequenceNum) { 917 JmriJOptionPane.showMessageDialog(null, rbx 918 .getString("Message34"), Bundle.getMessage("ErrorTitle"), 919 JmriJOptionPane.ERROR_MESSAGE); 920 return 0; 921 } 922 return n; 923 } 924 925 /** 926 * After any add, delete etc the section sequence numbers need to be 927 * rebuilt. 928 * After which we update sequence Number spinner on pane. 929 * Limit spinner to highest sequence index in 930 * section table (column 0). 931 */ 932 void updateSeqNum() { 933 int seqMax = 0; 934 int seqNumber = 0; 935 for (int ix = 0; ix<alternate.size();ix++) { 936 if (!alternate.get(ix)) { 937 seqNumber++; 938 } 939 sequence.set(ix,seqNumber); 940 } 941 seqMax = seqNumber; 942 seqNum.setModel(new SpinnerNumberModel( 943 seqMax, // initial value set 944 Math.min(seqMax, 1), // minimum value, either 0 (empty list) or 1 945 seqMax, // maximum order number 946 1)); 947 seqNum.setValue(Math.min(seqMax, 1)); 948 } 949 950 void deleteAlternateForSeqPressed(ActionEvent e) { 951 if (sectionList.size() <= 1) { 952 deleteAllSections(e); 953 } else { 954 int seq = getSeqNum(); 955 if (seq == 0) { 956 return; 957 } 958 for (int i = sectionList.size() - 1; i >= seq; i--) { 959 if ((sequence.get(i) == seq) && alternate.get(i)) { 960 removeSupportingArrayEntries(i); 961 } 962 } 963 initializeSectionCombos(); 964 } 965 updateSeqNum(); 966 sectionTableModel.fireTableDataChanged(); 967 } 968 969 void addAlternateForSeqPressed(ActionEvent e) { 970 int seq = getSeqNum(); 971 if (seq == 0) { 972 return; 973 } 974 Section primarySection = null; 975 List<Section> altOldList = new ArrayList<>(); 976 Section beforeSection = null; 977 int beforeSectionDirection = 0; 978 Section afterSection = null; 979 int afterSectionDirection = 0; 980 int index = -1; 981 for (int i = 0; i < sectionList.size(); i++) { 982 if ((sequence.get(i) == seq) && (!alternate.get(i))) { 983 primarySection = sectionList.get(i); 984 index = i; 985 } 986 if ((sequence.get(i) == seq) && alternate.get(i)) { 987 altOldList.add(sectionList.get(i)); 988 } 989 if ((sequence.get(i) == (seq - 1)) && (!alternate.get(i))) { 990 beforeSection = sectionList.get(i); 991 beforeSectionDirection = direction.get(i); 992 } 993 if ((sequence.get(i) == (seq + 1)) && (!alternate.get(i))) { 994 afterSection = sectionList.get(i); 995 afterSectionDirection = Section.FORWARD; 996 if (afterSectionDirection == direction.get(i)) { 997 afterSectionDirection = Section.REVERSE; 998 } 999 } 1000 } 1001 if (primarySection == null) { 1002 log.error("Missing primary Section for seq = {}", seq); 1003 return; 1004 } 1005 List<Section> possibles = new ArrayList<>(); 1006 List<Integer> possiblesDirection = new ArrayList<>(); 1007 List<String> possibleNames = new ArrayList<>(); 1008 for (Section s : sectionManager.getNamedBeanSet()) { 1009 Section mayBeSection = null; 1010 String mayBeName = s.getDisplayName(); 1011 int mayBeDirection = 0; 1012 if ((s != primarySection) && (s != beforeSection) 1013 && (s != afterSection) && (!inSectionList(s, altOldList))) { 1014 if (beforeSection != null) { 1015 if (forwardConnected(s, beforeSection, beforeSectionDirection)) { 1016 mayBeSection = s; 1017 mayBeDirection = Section.FORWARD; 1018 } else if (reverseConnected(s, beforeSection, beforeSectionDirection)) { 1019 mayBeSection = s; 1020 mayBeDirection = Section.REVERSE; 1021 } 1022 if ((mayBeSection != null) && (afterSection != null)) { 1023 if (mayBeDirection == Section.REVERSE) { 1024 if (!forwardConnected(s, afterSection, afterSectionDirection)) { 1025 mayBeSection = null; 1026 } 1027 } else { 1028 if (!reverseConnected(s, afterSection, afterSectionDirection)) { 1029 mayBeSection = null; 1030 } 1031 } 1032 } 1033 } else if (afterSection != null) { 1034 if (forwardConnected(s, afterSection, afterSectionDirection)) { 1035 mayBeSection = s; 1036 mayBeDirection = Section.REVERSE; 1037 } else if (reverseConnected(s, afterSection, afterSectionDirection)) { 1038 mayBeSection = s; 1039 mayBeDirection = Section.FORWARD; 1040 } 1041 } else { 1042 mayBeSection = s; 1043 mayBeDirection = Section.FORWARD; 1044 } 1045 if (mayBeSection != null) { 1046 possibles.add(mayBeSection); 1047 possiblesDirection.add(mayBeDirection); 1048 possibleNames.add(mayBeName); 1049 } 1050 } 1051 } 1052 if (possibles.isEmpty()) { 1053 JmriJOptionPane.showMessageDialog(addFrame, 1054 java.text.MessageFormat.format(rbx.getString("Message37"), 1055 new Object[]{"" + seq}), Bundle.getMessage("ErrorTitle"), 1056 JmriJOptionPane.ERROR_MESSAGE); 1057 return; 1058 } 1059 int k = 0; 1060 if (possibles.size() > 1) { 1061 Object choices[] = new Object[possibles.size()]; 1062 for (int j = 0; j < possibles.size(); j++) { 1063 choices[j] = possibleNames.get(j); 1064 } 1065 Object selName = JmriJOptionPane.showInputDialog(addFrame, 1066 rbx.getString("AddAlternateChoice"), 1067 rbx.getString("AddAlternateTitle"), 1068 JmriJOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 1069 if (selName == null) { 1070 return; 1071 } 1072 for (int j = 0; j < possibles.size(); j++) { 1073 if (selName.equals(choices[j])) { 1074 k = j; 1075 } 1076 } 1077 } 1078 index = index + 1 + altOldList.size(); 1079 sectionList.add(index, possibles.get(k)); 1080 direction.add(index, possiblesDirection.get(k)); 1081 sequence.add(index, sequence.get(index - 1)); 1082 alternate.add(index, true); 1083 safe.add(index, addAsSafe.isSelected()); 1084 if (stopAllocatingSensorBox.getSelectedIndex() < 0) { 1085 sensorStopAllocation.add(index, ""); 1086 } else { 1087 sensorStopAllocation.add(index, (String) stopAllocatingSensorBox.getSelectedItem()); 1088 } 1089 if (stopAllocatingSensorBox.getSelectedIndex() < 0) { 1090 sensorStopAllocation.add(index, ""); 1091 } else { 1092 sensorStopAllocation.add(index, (String) stopAllocatingSensorBox.getSelectedItem()); 1093 } 1094 fwdStopPerCent.add(index, Float.valueOf(1.0f)); 1095 revStopPerCent.add(index, Float.valueOf(1.0f)); 1096 action.add(index, new ArrayList<>()); 1097 initializeSectionCombos(); 1098 updateSeqNum(); 1099 sectionTableModel.fireTableDataChanged(); 1100 } 1101 1102 void addAlternateSectionPressed(ActionEvent e) { 1103 if (alternateSectionBoxList.isEmpty()) { 1104 JmriJOptionPane.showMessageDialog(addFrame, rbx 1105 .getString("Message24"), Bundle.getMessage("ErrorTitle"), 1106 JmriJOptionPane.ERROR_MESSAGE); 1107 return; 1108 } 1109 int index = alternateSectionBox.getSelectedIndex(); 1110 Section s = alternateSectionBoxList.get(index); 1111 if (s != null) { 1112 sectionList.add(s); 1113 direction.add(altSectionDirection.get(index)); 1114 sequence.add(curSequenceNum); 1115 action.add(new ArrayList<>()); 1116 alternate.add(true); 1117 safe.add(addAsSafe.isSelected()); 1118 sensorStopAllocation.add((String)stopAllocatingSensorBox.getSelectedItem()); 1119 fwdStopPerCent.add( Float.valueOf(1.0f)); 1120 revStopPerCent.add( Float.valueOf(1.0f)); 1121 initializeSectionCombos(); 1122 } 1123 updateSeqNum(); 1124 sectionTableModel.fireTableDataChanged(); 1125 } 1126 1127 void createPressed(ActionEvent e) { 1128 if (!checkTransitInformation()) { 1129 return; 1130 } 1131 String uName = userName.getText(); 1132 if (uName.isEmpty()) { 1133 uName = null; 1134 } 1135 1136 try { 1137 // attempt to create the new Transit 1138 if (_autoSystemName.isSelected()) { 1139 curTransit = transitManager.createNewTransit(uName); 1140 } else { 1141 String sName = sysName.getText(); 1142 curTransit = transitManager.createNewTransit(sName, uName); 1143 } 1144 } catch (IllegalArgumentException ex) { 1145 JmriJOptionPane.showMessageDialog(addFrame, ex.getLocalizedMessage(), Bundle.getMessage("ErrorTitle"), 1146 JmriJOptionPane.ERROR_MESSAGE); 1147 return; 1148 } 1149 sysName.setText(curTransit.getSystemName()); 1150 setTransitInformation(); 1151 addFrame.setVisible(false); 1152 pref.setSimplePreferenceState(systemNameAuto, _autoSystemName.isSelected()); 1153 } 1154 1155 void cancelPressed(ActionEvent e) { 1156 addFrame.setVisible(false); 1157 sectionTableModel.dispose(); 1158 addFrame.dispose(); // remove addFrame from Windows menu 1159 addFrame = null; 1160 } 1161 1162 void updatePressed(ActionEvent e) { 1163 if (!checkTransitInformation()) { 1164 return; 1165 } 1166 // check if user name has been changed 1167 String uName = userName.getText(); 1168 if (uName.isEmpty()) { 1169 uName = null; 1170 } 1171 if ((uName != null) && (!uName.equals(curTransit.getUserName()))) { 1172 // check that new user name is unique 1173 Transit tTransit = transitManager.getByUserName(uName); 1174 if (tTransit != null) { 1175 JmriJOptionPane.showMessageDialog(addFrame, rbx 1176 .getString("Message22"), Bundle.getMessage("ErrorTitle"), 1177 JmriJOptionPane.ERROR_MESSAGE); 1178 return; 1179 } 1180 } 1181 curTransit.setUserName(uName); 1182 if (setTransitInformation()) { 1183 // successful update 1184 addFrame.setVisible(false); 1185 sectionTableModel.dispose(); 1186 addFrame.dispose(); // remove addFrame from Windows menu 1187 addFrame = null; 1188 } 1189 } 1190 1191 private void removeSupportingArrayEntries(int index) { 1192 sectionList.remove(index); 1193 sequence.remove(index); 1194 direction.remove(index); 1195 action.remove(index); 1196 alternate.remove(index); 1197 safe.remove(index); 1198 sensorStopAllocation.remove(index); 1199 fwdStopPerCent.remove(index); 1200 revStopPerCent.remove(index); 1201 } 1202 1203 private boolean checkTransitInformation() { 1204 //transits can now be of length 1 segmant. 1205 //With these the route has to start outside the transit 1206 if ((sectionList.size() < 1) || (curSequenceNum < 1)) { 1207 JmriJOptionPane.showMessageDialog(addFrame, rbx 1208 .getString("Message26"), Bundle.getMessage("ErrorTitle"), 1209 JmriJOptionPane.ERROR_MESSAGE); 1210 return false; 1211 } 1212 return true; 1213 } 1214 1215 private boolean setTransitInformation() { 1216 if (curTransit == null) { 1217 return false; 1218 } 1219 curTransit.removeAllSections(); 1220 for (int i = 0; i < sectionList.size(); i++) { 1221 TransitSection ts = new TransitSection(sectionList.get(i), 1222 sequence.get(i), direction.get(i), alternate.get(i), safe.get(i), 1223 sensorStopAllocation.get(i), fwdStopPerCent.get(i), revStopPerCent.get(i)); 1224 List<TransitSectionAction> list = action.get(i); 1225 if (list != null) { 1226 for (int j = 0; j < list.size(); j++) { 1227 ts.addAction(list.get(j)); 1228 } 1229 } 1230 curTransit.addTransitSection(ts); 1231 } 1232 return true; 1233 } 1234 1235 private void initializeSectionCombos() { 1236 primarySectionBox.removeAllItems(); 1237 alternateSectionBox.removeAllItems(); 1238 insertAtBeginningBox.removeAllItems(); 1239 primarySectionBoxList.clear(); 1240 alternateSectionBoxList.clear(); 1241 insertAtBeginningBoxList.clear(); 1242 priSectionDirection.clear(); 1243 altSectionDirection.clear(); 1244 insertAtBeginningDirection.clear(); 1245 if (sectionList.isEmpty()) { 1246 // no Sections currently in Transit - all Sections and all Directions OK 1247 for (Section s : sectionManager.getNamedBeanSet()) { 1248 String sName = s.getDisplayName(); 1249 primarySectionBox.addItem(sName); 1250 primarySectionBoxList.add(s); 1251 priSectionDirection.add(Section.FORWARD); 1252 } 1253 } else { 1254 // limit to Sections that connect to the current Section and are not the previous Section 1255 for (Section s : sectionManager.getNamedBeanSet()) { 1256 String sName = s.getDisplayName(); 1257 if ((s != prevSection) && (forwardConnected(s, curSection, curSectionDirection))) { 1258 primarySectionBox.addItem(sName); 1259 primarySectionBoxList.add(s); 1260 priSectionDirection.add(Section.FORWARD); 1261 } else if ((s != prevSection) && (reverseConnected(s, curSection, curSectionDirection))) { 1262 primarySectionBox.addItem(sName); 1263 primarySectionBoxList.add(s); 1264 priSectionDirection.add(Section.REVERSE); 1265 } 1266 } 1267 // check if there are any alternate Section choices 1268 if (prevSection != null) { 1269 for (Section s : sectionManager.getNamedBeanSet()) { 1270 String sName = s.getDisplayName(); 1271 if ((notIncludedWithSeq(s, curSequenceNum)) 1272 && forwardConnected(s, prevSection, prevSectionDirection)) { 1273 alternateSectionBox.addItem(sName); 1274 alternateSectionBoxList.add(s); 1275 altSectionDirection.add( Section.FORWARD); 1276 } else if (notIncludedWithSeq(s, curSequenceNum) 1277 && reverseConnected(s, prevSection, prevSectionDirection)) { 1278 alternateSectionBox.addItem(sName); 1279 alternateSectionBoxList.add(s); 1280 altSectionDirection.add(Section.REVERSE); 1281 } 1282 } 1283 } 1284 // check if there are any Sections available to be inserted at beginning 1285 Section firstSection = sectionList.get(0); 1286 int testDirection = Section.FORWARD; 1287 if (direction.get(0) == Section.FORWARD) { 1288 testDirection = Section.REVERSE; 1289 } 1290 for (Section s : sectionManager.getNamedBeanSet()) { 1291 String sName = s.getDisplayName(); 1292 if ((s != firstSection) && (forwardConnected(s, firstSection, testDirection))) { 1293 insertAtBeginningBox.addItem(sName); 1294 insertAtBeginningBoxList.add(s); 1295 insertAtBeginningDirection.add( Section.REVERSE); 1296 } else if ((s != firstSection) && (reverseConnected(s, firstSection, testDirection))) { 1297 insertAtBeginningBox.addItem(sName); 1298 insertAtBeginningBoxList.add(s); 1299 insertAtBeginningDirection.add( Section.FORWARD); 1300 } 1301 } 1302 } 1303 JComboBoxUtil.setupComboBoxMaxRows(primarySectionBox); 1304 JComboBoxUtil.setupComboBoxMaxRows(alternateSectionBox); 1305 JComboBoxUtil.setupComboBoxMaxRows(insertAtBeginningBox); 1306 } 1307 1308 private boolean forwardConnected(Section s1, Section s2, int restrictedDirection) { 1309 if ((s1 != null) && (s2 != null)) { 1310 List<EntryPoint> s1ForwardEntries = s1.getForwardEntryPointList(); 1311 List<EntryPoint> s2Entries; 1312 switch (restrictedDirection) { 1313 case Section.FORWARD: 1314 s2Entries = s2.getReverseEntryPointList(); 1315 break; 1316 case Section.REVERSE: 1317 s2Entries = s2.getForwardEntryPointList(); 1318 break; 1319 default: 1320 s2Entries = s2.getEntryPointList(); 1321 break; 1322 } 1323 for (int i = 0; i < s1ForwardEntries.size(); i++) { 1324 Block b1 = s1ForwardEntries.get(i).getFromBlock(); 1325 for (int j = 0; j < s2Entries.size(); j++) { 1326 Block b2 = s2Entries.get(j).getFromBlock(); 1327 if ((b1 == s2Entries.get(j).getBlock()) 1328 && (b2 == s1ForwardEntries.get(i).getBlock())) { 1329 return true; 1330 } 1331 } 1332 } 1333 } 1334 return false; 1335 } 1336 1337 private boolean reverseConnected(Section s1, Section s2, int restrictedDirection) { 1338 if ((s1 != null) && (s2 != null)) { 1339 List<EntryPoint> s1ReverseEntries = s1.getReverseEntryPointList(); 1340 List<EntryPoint> s2Entries; 1341 switch (restrictedDirection) { 1342 case Section.FORWARD: 1343 s2Entries = s2.getReverseEntryPointList(); 1344 break; 1345 case Section.REVERSE: 1346 s2Entries = s2.getForwardEntryPointList(); 1347 break; 1348 default: 1349 s2Entries = s2.getEntryPointList(); 1350 break; 1351 } 1352 for (int i = 0; i < s1ReverseEntries.size(); i++) { 1353 Block b1 = s1ReverseEntries.get(i).getFromBlock(); 1354 for (int j = 0; j < s2Entries.size(); j++) { 1355 Block b2 = s2Entries.get(j).getFromBlock(); 1356 if ((b1 == s2Entries.get(j).getBlock()) 1357 && (b2 == s1ReverseEntries.get(i).getBlock())) { 1358 return true; 1359 } 1360 } 1361 } 1362 } 1363 return false; 1364 } 1365 1366 private boolean notIncludedWithSeq(Section s, int seq) { 1367 for (int i = 0; i < sectionList.size(); i++) { 1368 if ((sectionList.get(i) == s) && (seq == sequence.get(i))) { 1369 return false; 1370 } 1371 } 1372 return true; 1373 } 1374 1375 private void autoSystemName() { 1376 if (_autoSystemName.isSelected()) { 1377// create.setEnabled(true); 1378 sysName.setEnabled(false); 1379 sysNameLabel.setEnabled(false); 1380 } else { 1381// if (sysName.getText().length() > 0) 1382// create.setEnabled(true); 1383// else 1384// create.setEnabled(false); 1385 sysName.setEnabled(true); 1386 sysNameLabel.setEnabled(true); 1387 } 1388 } 1389 1390 // variables for View Actions window 1391 private int activeRow = 0; 1392 private SpecialActionTableModel actionTableModel = null; 1393 private JmriJFrame actionTableFrame = null; 1394 private final JLabel fixedSectionLabel = new JLabel("X"); 1395 1396 private void addEditActionsPressed(int r) { 1397 activeRow = r; 1398 if (actionTableModel != null) { 1399 actionTableModel.fireTableStructureChanged(); 1400 } 1401 if (actionTableFrame == null) { 1402 actionTableFrame = new JmriJFrame(rbx.getString("TitleViewActions")); 1403 actionTableFrame.addHelpMenu( 1404 "package.jmri.jmrit.beantable.ViewSpecialActions", true); 1405 Container contentPane = actionTableFrame.getContentPane(); 1406 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 1407 JPanel panel1 = new JPanel(); 1408 panel1.setLayout(new FlowLayout()); 1409 JLabel sectionNameLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("BeanNameSection"))); 1410 panel1.add(sectionNameLabel); 1411 panel1.add(fixedSectionLabel); 1412 contentPane.add(panel1); 1413 addFrame.getContentPane().add(new JSeparator()); 1414 JPanel pct = new JPanel(); 1415 pct.setLayout(new BorderLayout()); 1416 // initialize table of actions 1417 actionTableModel = new SpecialActionTableModel(); 1418 JTable actionTable = new JTable(actionTableModel); 1419 actionTable.setRowSelectionAllowed(false); 1420 TableColumnModel actionColumnModel = actionTable 1421 .getColumnModel(); 1422 TableColumn whenColumn = actionColumnModel 1423 .getColumn(SpecialActionTableModel.WHEN_COLUMN); 1424 whenColumn.setResizable(true); 1425 TableColumn whatColumn = actionColumnModel 1426 .getColumn(SpecialActionTableModel.WHAT_COLUMN); 1427 whatColumn.setResizable(true); 1428 TableColumn editColumn = actionColumnModel 1429 .getColumn(SpecialActionTableModel.EDIT_COLUMN); 1430 // install button renderer and editor 1431 ButtonRenderer buttonRenderer = new ButtonRenderer(); 1432 actionTable.setDefaultRenderer(JButton.class, buttonRenderer); 1433 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 1434 actionTable.setDefaultEditor(JButton.class, buttonEditor); 1435 JButton testButton = new JButton(Bundle.getMessage("ButtonDelete")); 1436 actionTable.setRowHeight(testButton.getPreferredSize().height); 1437 editColumn.setResizable(false); 1438 editColumn.setMinWidth(testButton.getPreferredSize().width); 1439 editColumn.setMaxWidth(testButton.getPreferredSize().width); 1440 TableColumn removeColumn = actionColumnModel 1441 .getColumn(SpecialActionTableModel.REMOVE_COLUMN); 1442 removeColumn.setMinWidth(testButton.getPreferredSize().width); 1443 removeColumn.setMaxWidth(testButton.getPreferredSize().width); 1444 removeColumn.setResizable(false); 1445 JScrollPane actionTableScrollPane = new JScrollPane( 1446 actionTable); 1447 pct.add(actionTableScrollPane, BorderLayout.CENTER); 1448 contentPane.add(pct); 1449 pct.setVisible(true); 1450 // add View Action panel buttons 1451 JPanel but = new JPanel(); 1452 but.setLayout(new BoxLayout(but, BoxLayout.Y_AXIS)); 1453 JPanel panel4 = new JPanel(); 1454 panel4.setLayout(new FlowLayout()); 1455 JButton newActionButton = new JButton(rbx.getString("ButtonAddNewAction")); 1456 panel4.add(newActionButton); 1457 newActionButton.addActionListener(this::newActionPressed); 1458 newActionButton.setToolTipText(rbx.getString("NewActionButtonHint")); 1459 JButton doneButton = new JButton(Bundle.getMessage("ButtonDone")); 1460 panel4.add(doneButton); 1461 doneButton.addActionListener(this::doneWithActionsPressed); 1462 doneButton.setToolTipText(rbx.getString("DoneButtonHint")); 1463 but.add(panel4); 1464 contentPane.add(but); 1465 } 1466 fixedSectionLabel.setText(getSectionNameByRow(r) + " " 1467 + rbx.getString("SequenceAbbrev") + ": " + sequence.get(r)); 1468 actionTableFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1469 @Override 1470 public void windowClosing(java.awt.event.WindowEvent e) { 1471 actionTableFrame.setVisible(false); 1472 actionTableFrame.dispose(); 1473 actionTableFrame = null; 1474 if (addEditActionFrame != null) { 1475 addEditActionFrame.setVisible(false); 1476 addEditActionFrame.dispose(); 1477 addEditActionFrame = null; 1478 } 1479 } 1480 }); 1481 actionTableFrame.pack(); 1482 actionTableFrame.setVisible(true); 1483 } 1484 1485 private void doneWithActionsPressed(ActionEvent e) { 1486 actionTableFrame.setVisible(false); 1487 actionTableFrame.dispose(); 1488 actionTableFrame = null; 1489 if (addEditActionFrame != null) { 1490 addEditActionFrame.setVisible(false); 1491 addEditActionFrame.dispose(); 1492 addEditActionFrame = null; 1493 } 1494 } 1495 1496 private void newActionPressed(ActionEvent e) { 1497 editActionMode = false; 1498 curTSA = null; 1499 addEditActionWindow(); 1500 } 1501 1502 // variables for Add/Edit Action window 1503 private boolean editActionMode = false; 1504 private JmriJFrame addEditActionFrame = null; 1505 private TransitSectionAction curTSA = null; 1506 private final JComboBox<String> whenBox = new JComboBox<>(); 1507 private final NamedBeanComboBox<Sensor> whenSensorComboBox = new NamedBeanComboBox<>( 1508 InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME); 1509 private final JSpinner whenDataSpinnerFloat = new JSpinner(new SpinnerNumberModel( 1510 Float.valueOf(0.0f), Float.valueOf(0.0f), Float.valueOf(65.0f), Float.valueOf(0.5f))); // delay 1511 private final JSpinner whenDataSpinnerInt = new JSpinner(new SpinnerNumberModel(0, 0, 65000, 100)); // delay 1512 private final JRadioButton mSecButton = new JRadioButton(Bundle.getMessage("LabelMilliseconds")); 1513 private final JRadioButton secButton = new JRadioButton(Bundle.getMessage("LabelSeconds")); 1514 private final JComboBox<String> whatBox = new JComboBox<>(); 1515 private final JSpinner whatPercentSpinner = new JSpinner(); // speed 1516 private final JSpinner whatMinuteSpinner1 = new JSpinner(new SpinnerNumberModel(1, 1, 65500, 1)); // time in ms 1517 private final JSpinner whatMinuteSpinner2 = new JSpinner(new SpinnerNumberModel(100, 100, 65500, 1)); // time in ms 1518 private final JSpinner locoFunctionSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 28, 1)); // function ID 1519 private final JTextField whatStringField = new JTextField(12); 1520 private final JTextField locoAddress = new JTextField(12); 1521 private final RosterEntryComboBox rosterComboBox = new RosterEntryComboBox(); 1522 private final JComboBox<String> trainInfoComboBox = new JComboBox<>(); 1523 private final JRadioButton locoAddressDefault = new JRadioButton(rbx.getString("TrainInfoUseDefault")); 1524 private final JRadioButton locoAddressRoster = new JRadioButton(rbx.getString("TrainInfoUseRoster")); 1525 private final JRadioButton locoAddressNumber = new JRadioButton(rbx.getString("TrainInfoUseAddress")); 1526 private final JRadioButton locoAddressCurrent = new JRadioButton(rbx.getString("TrainInfoUseCurrentAddress")); 1527 private final ButtonGroup locoAddressGroup = new ButtonGroup(); 1528 private JButton updateActionButton = null; 1529 private JButton createActionButton = null; 1530 private JButton cancelAddEditActionButton = null; 1531 private final JComboBox<String> blockBox = new JComboBox<>(); 1532 private List<Block> blockList = new ArrayList<>(); 1533 private final JRadioButton onButton = new JRadioButton(Bundle.getMessage("StateOn")); 1534 private final JRadioButton offButton = new JRadioButton(Bundle.getMessage("StateOff")); 1535 private final JLabel doneSensorLabel = new JLabel(rbx.getString("DoneSensorLabel")); 1536 private JPanel signalPanel; 1537 private JPanel panelPercentageSpinner; 1538 private JPanel panelDelay; 1539 private final JLabel panelDelayLabel = new JLabel(); 1540 private JPanel panelWhatBox; 1541 private JPanel panelLoadTrainInfo; 1542 private final NamedBeanComboBox<Sensor> doneSensorComboBox = new NamedBeanComboBox<>( 1543 InstanceManager.getDefault(SensorManager.class), null, DisplayOptions.DISPLAYNAME); 1544 private final NamedBeanComboBox<SignalMast> signalMastComboBox = new NamedBeanComboBox<>( 1545 InstanceManager.getDefault(SignalMastManager.class), null, DisplayOptions.DISPLAYNAME); 1546 private final NamedBeanComboBox<SignalHead> signalHeadComboBox = new NamedBeanComboBox<>( 1547 InstanceManager.getDefault(SignalHeadManager.class), null, DisplayOptions.DISPLAYNAME); 1548 1549 private void addEditActionWindow() { 1550 if (addEditActionFrame == null) { 1551 // set up add/edit action window 1552 addEditActionFrame = new JmriJFrame(rbx.getString("TitleAddAction")); 1553 addEditActionFrame.addHelpMenu( 1554 "package.jmri.jmrit.beantable.TransitSectionAddEditAction", true); 1555 Container contentPane = addEditActionFrame.getContentPane(); 1556 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 1557 // to set When to start the action 1558 JPanel panelx = new JPanel(); 1559 panelx.setLayout(new BoxLayout(panelx, BoxLayout.Y_AXIS)); 1560 JPanel panel1 = new JPanel(); 1561 panel1.setLayout(new FlowLayout()); 1562 panel1.add(new JLabel(rbx.getString("WhenText"))); 1563 initializeWhenBox(); 1564 JComboBoxUtil.setupComboBoxMaxRows(whenBox); 1565 panel1.add(whenBox); 1566 whenBox.addActionListener((ActionEvent e) -> { 1567 log.debug("whenBox was set"); 1568 if (whenBox.getSelectedItem()!=null) { 1569 setWhen(getWhenMenuCode((String)whenBox.getSelectedItem())); 1570 } 1571 }); 1572 whenBox.setToolTipText(rbx.getString("WhenBoxTip")); 1573 JComboBoxUtil.setupComboBoxMaxRows(whenSensorComboBox); 1574 panel1.add(whenSensorComboBox); 1575 whenSensorComboBox.setAllowNull(true); 1576 initializeBlockBox(); 1577 JComboBoxUtil.setupComboBoxMaxRows(blockBox); 1578 panel1.add(blockBox); 1579 panelx.add(panel1); 1580 // to set optional delay setting 1581 panelDelay = new JPanel(); 1582 panelDelay.setLayout(new FlowLayout()); 1583 panelDelayLabel.setText(" " + rbx.getString("OptionalDelay") + ": "); 1584 panelDelay.add(panelDelayLabel); 1585 panelDelay.add(whenDataSpinnerInt); 1586 whenDataSpinnerInt.setToolTipText(rbx.getString("HintDelayData")); 1587 whenDataSpinnerInt.addChangeListener((ChangeEvent e) -> { 1588 if (mSecButton.isSelected()) { 1589 float fl = (int)whenDataSpinnerInt.getValue(); 1590 whenDataSpinnerFloat.setValue(fl/1000.0f); 1591 } 1592 }); 1593 panelDelay.add(whenDataSpinnerFloat); 1594 whenDataSpinnerFloat.setToolTipText(rbx.getString("HintDelayData")); 1595 whenDataSpinnerFloat.setPreferredSize(whenDataSpinnerInt.getPreferredSize()); 1596 whenDataSpinnerFloat.addChangeListener( e -> { 1597 if (secButton.isSelected()) { 1598 float dVal = (float)whenDataSpinnerFloat.getValue(); 1599 dVal *= 1000.0; 1600 whenDataSpinnerInt.setValue(Math.round(dVal)); 1601 } 1602 }); 1603 ButtonGroup secMsec = new ButtonGroup(); 1604 secMsec.add(mSecButton); 1605 secMsec.add(secButton); 1606 panelDelay.add(mSecButton); 1607 mSecButton.addChangeListener( e -> { 1608 if (mSecButton.isSelected()) { 1609 whenDataSpinnerFloat.setVisible(false); 1610 whenDataSpinnerInt.setVisible(true); 1611 } 1612 }); 1613 panelDelay.add(secButton); 1614 secButton.addChangeListener( e -> { 1615 if (secButton.isSelected()) { 1616 whenDataSpinnerFloat.setVisible(true); 1617 whenDataSpinnerInt.setVisible(false); 1618 } 1619 }); 1620 secButton.setSelected(true); 1621 panelx.add(panelDelay); 1622 JPanel spacer = new JPanel(); 1623 spacer.setLayout(new FlowLayout()); 1624 spacer.add(new JLabel(" ")); 1625 panelx.add(spacer); 1626 // to set What action to take 1627 panelWhatBox = new JPanel(); 1628 panelWhatBox.setLayout(new FlowLayout()); 1629 panelWhatBox.add(new JLabel(rbx.getString("WhatText"))); 1630 initializeWhatBox(0); 1631 JComboBoxUtil.setupComboBoxMaxRows(whatBox); 1632 panelWhatBox.add(whatBox); 1633 whatBox.setToolTipText(rbx.getString("WhatBoxTip")); 1634 whatBox.addActionListener( e -> { 1635 if (whatBox.getSelectedItem()!=null) { 1636 setWhat(getWhatMenuCode((String)whatBox.getSelectedItem())); 1637 } 1638 }); 1639 panelWhatBox.add(whatStringField); 1640 whatStringField.setToolTipText(rbx.getString("HintSoundHornPatternString")); 1641 panelx.add(panelWhatBox); 1642 1643 // Train Info 1644 TitledBorder trainInfoBorder = BorderFactory.createTitledBorder(rbx.getString("SelectTrain")); 1645 panelLoadTrainInfo = new JPanel(); 1646 panelLoadTrainInfo.setLayout(new BoxLayout(panelLoadTrainInfo, BoxLayout.Y_AXIS)); 1647 panelLoadTrainInfo.setBorder(trainInfoBorder); 1648 JPanel panelUseInfo = new JPanel(); 1649 panelUseInfo.setBorder(trainInfoBorder); 1650 panelUseInfo.add(new JLabel(rbx.getString("TrainInfoFile"))); 1651 panelUseInfo.add(trainInfoComboBox); 1652 trainInfoComboBox.setToolTipText(rbx.getString("HintTrainInfoFile")); 1653 panelLoadTrainInfo.add(panelUseInfo); 1654 TitledBorder useLocoBorder = BorderFactory.createTitledBorder(rbx.getString("SelectALoco")); 1655 JPanel panelUseLoco = new JPanel(); 1656 panelUseLoco.setBorder(useLocoBorder); 1657 1658 locoAddressGroup.add(locoAddressDefault); 1659 locoAddressDefault.setToolTipText(rbx.getString("TrainInfoUseDefaultHint")); 1660 locoAddressDefault.addActionListener(this::updateTrainInfoAddressFields); 1661 panelUseLoco.add(locoAddressDefault); 1662 locoAddressGroup.add(locoAddressCurrent); 1663 locoAddressCurrent.setToolTipText(rbx.getString("TrainInfoUseCurrentAddressHint")); 1664 locoAddressCurrent.addActionListener(this::updateTrainInfoAddressFields); 1665 panelUseLoco.add(locoAddressCurrent); 1666 locoAddressGroup.add(locoAddressRoster); 1667 locoAddressRoster.addActionListener(this::updateTrainInfoAddressFields); 1668 panelUseLoco.add(locoAddressRoster); 1669 locoAddressGroup.add(locoAddressNumber); 1670 locoAddressNumber.addActionListener(this::updateTrainInfoAddressFields); 1671 panelUseLoco.add(locoAddressNumber); 1672 panelUseLoco.add(locoAddress); 1673 locoAddress.setToolTipText(rbx.getString("HintLocoMotiveAddress")); 1674 panelUseLoco.add(rosterComboBox); 1675 panelLoadTrainInfo.add(panelUseLoco); 1676 panelx.add(panelLoadTrainInfo); 1677 panelLoadTrainInfo.setVisible(false); 1678 1679 panelPercentageSpinner = new JPanel(); 1680 panelPercentageSpinner.setLayout(new FlowLayout()); 1681 whatPercentSpinner.setModel(new SpinnerNumberModel( 1682 Float.valueOf(1.0f), Float.valueOf(0.00f), Float.valueOf(1.5f), Float.valueOf(0.01f))); 1683 whatPercentSpinner.setEditor(new JSpinner.NumberEditor(whatPercentSpinner, "# %")); // show as a percentage % sign 1684 panelPercentageSpinner.add(whatPercentSpinner); 1685 panelPercentageSpinner.add(whatMinuteSpinner1); 1686 panelPercentageSpinner.add(whatMinuteSpinner2); 1687 panelPercentageSpinner.add(locoFunctionSpinner); 1688 // signal comboboxes 1689 TitledBorder border = BorderFactory.createTitledBorder(rbx.getString("SelectASignal")); 1690 signalPanel = new JPanel(); 1691 signalPanel.setBorder(border); 1692 signalPanel.add(new JLabel(rbx.getString("MastLabel"))); 1693 JComboBoxUtil.setupComboBoxMaxRows(signalMastComboBox); 1694 signalPanel.add(signalMastComboBox); 1695 signalMastComboBox.setAllowNull(true); 1696 signalMastComboBox.addActionListener((ActionEvent e) -> { 1697 if (signalMastComboBox.getSelectedIndex() > 0) { 1698 signalHeadComboBox.setSelectedIndex(-1); // choose either a head or a mast 1699 } 1700 }); 1701 signalPanel.add(new JLabel(rbx.getString("HeadLabel"))); 1702 JComboBoxUtil.setupComboBoxMaxRows(signalHeadComboBox); 1703 signalPanel.add(signalHeadComboBox); 1704 signalHeadComboBox.setAllowNull(true); 1705 signalHeadComboBox.addActionListener((ActionEvent e) -> { 1706 if (signalHeadComboBox.getSelectedIndex() > 0) { 1707 signalMastComboBox.setSelectedIndex(-1); // choose either a head or a mast 1708 } 1709 }); 1710 signalMastComboBox.setToolTipText(rbx.getString("HintSignalEntry")); 1711 signalHeadComboBox.setToolTipText(rbx.getString("HintSignalEntry")); 1712 panelPercentageSpinner.add(signalPanel); 1713 // On/Off buttons 1714 ButtonGroup onOffGroup = new ButtonGroup(); 1715 onOffGroup.add(onButton); 1716 onOffGroup.add(offButton); 1717 panelPercentageSpinner.add(onButton); 1718 panelPercentageSpinner.add(offButton); 1719 panelPercentageSpinner.add(doneSensorLabel); 1720 panelPercentageSpinner.add(doneSensorComboBox); 1721 JComboBoxUtil.setupComboBoxMaxRows(doneSensorComboBox); 1722 doneSensorComboBox.setAllowNull(true); 1723 panelx.add(panelPercentageSpinner); 1724 contentPane.add(panelx); 1725 contentPane.add(new JSeparator()); 1726 // add buttons 1727 JPanel but = new JPanel(); 1728 but.setLayout(new FlowLayout()); 1729 but.add(cancelAddEditActionButton = new JButton(Bundle.getMessage("ButtonCancel"))); 1730 cancelAddEditActionButton.addActionListener(this::cancelAddEditActionPressed); 1731 cancelAddEditActionButton.setToolTipText(rbx.getString("CancelButtonHint")); 1732 createActionButton = new JButton(rbx.getString("CreateActionButton")); 1733 but.add(createActionButton); 1734 createActionButton.addActionListener(this::createActionPressed); 1735 createActionButton.setToolTipText(rbx.getString("CreateActionButtonHint")); 1736 updateActionButton = new JButton(rbx.getString("UpdateActionButton")); 1737 but.add(updateActionButton); 1738 updateActionButton.addActionListener(this::updateActionPressed); 1739 updateActionButton.setToolTipText(rbx.getString("UpdateActionButtonHint")); 1740 contentPane.add(but); 1741 } 1742 if (editActionMode) { 1743 // initialize window for the action being edited 1744 addEditActionFrame.setTitle(rbx.getString("TitleEditAction")); 1745 updateActionButton.setVisible(true); 1746 createActionButton.setVisible(false); 1747 whenDataSpinnerInt.setValue(curTSA.getDataWhen()); 1748 float whenFloat = (int)whenDataSpinnerInt.getValue(); 1749 whenDataSpinnerFloat.setValue(whenFloat/1000.0f); 1750 whenSensorComboBox.setSelectedItemByName(curTSA.getStringWhen()); 1751 // spinners are set in setWhat() 1752 tWhatString2 = curTSA.getStringWhat2(); 1753 tWhatString = curTSA.getStringWhat(); 1754 tWhatData1 = curTSA.getDataWhat1(); 1755 tWhat = curTSA.getWhatCode(); 1756 tWhen = curTSA.getWhenCode(); 1757 tWhenData = curTSA.getDataWhen(); 1758 tWhatData2 = curTSA.getDataWhat2(); 1759 whatStringField.setText(tWhatString); 1760 onButton.setSelected(true); 1761 if ("Off".equals(curTSA.getStringWhat())) { 1762 offButton.setSelected(true); 1763 } 1764 locoAddress.setText(curTSA.getStringWhat2()); 1765 panelLoadTrainInfo.setVisible(false); 1766 log.debug("setWhen called for edit of action, editmode = {}", editActionMode); 1767 whenBox.setSelectedItem(getWhenMenuText(curTSA.getWhenCode())); 1768 // setWhen(curTSA.getWhenCode()) and setWhat(idem) are set via whenBox and whatBox 1769 whatBox.setSelectedItem(getWhatMenuText(curTSA.getWhatCode())); 1770 setBlockBox(); 1771 } else { 1772 // initialize for add new action 1773 addEditActionFrame.setTitle(rbx.getString("TitleAddAction")); 1774 whenBox.setSelectedIndex(0); 1775 // setWhen(1) and setWhat(1) are set from the whenBox and whatBox listeners 1776 whatBox.setSelectedIndex(0); 1777 // set initial values after setting model 1778 whenDataSpinnerInt.setValue(0); 1779 whenDataSpinnerFloat.setValue(0.0f); 1780 whenSensorComboBox.setSelectedItem(0); 1781 whatPercentSpinner.setValue(1.0f); 1782 whatMinuteSpinner1.setValue(100); 1783 whatMinuteSpinner2.setValue(100); 1784 locoFunctionSpinner.setValue(0); 1785 signalMastComboBox.setSelectedItem(0); 1786 signalHeadComboBox.setSelectedItem(0); 1787 doneSensorComboBox.setSelectedItem(0); 1788 whatStringField.setText(""); 1789 locoAddress.setText(""); 1790 onButton.setSelected(true); 1791 updateActionButton.setVisible(false); 1792 createActionButton.setVisible(true); 1793 panelLoadTrainInfo.setVisible(false); 1794 setBlockBox(); 1795 } 1796 addEditActionFrame.addWindowListener(new java.awt.event.WindowAdapter() { 1797 @Override 1798 public void windowClosing(java.awt.event.WindowEvent e) { 1799 addEditActionFrame.setVisible(false); 1800 addEditActionFrame.dispose(); 1801 addEditActionFrame = null; 1802 } 1803 }); 1804 addEditActionFrame.pack(); 1805 addEditActionFrame.setVisible(true); 1806 } 1807 1808 /** 1809 * Set special stuff depending on When selected. 1810 * 1811 * @param code selected item in getWhenBox 1812 */ 1813 private void setWhen(int code) { 1814 // setting the whenBox here causes recursion 1815 whenSensorComboBox.setVisible(false); 1816 blockBox.setVisible(false); 1817 panelDelay.setVisible(true); 1818 panelWhatBox.setVisible(true); 1819 panelPercentageSpinner.setVisible(true); 1820 panelDelayLabel.setText(" " + rbx.getString("OptionalDelay") + ": "); 1821 log.debug("setWhen code = {}", code); 1822 initializeWhatBox(code); 1823 switch (code) { 1824 case TransitSectionAction.EXIT: 1825 panelDelay.setVisible(false); 1826 break; 1827 case TransitSectionAction.ENTRY: 1828 case TransitSectionAction.TRAINSTOP: 1829 case TransitSectionAction.TRAINSTART: 1830 case TransitSectionAction.PRESTARTACTION: 1831 break; 1832 case TransitSectionAction.PRESTARTDELAY: 1833 panelDelay.setVisible(true); 1834 panelDelayLabel.setText(" " + rbx.getString("Delay") + ": "); 1835 panelWhatBox.setVisible(false); 1836 panelPercentageSpinner.setVisible(false); 1837 break; 1838 case TransitSectionAction.BLOCKENTRY: 1839 case TransitSectionAction.BLOCKEXIT: 1840 blockBox.setVisible(true); 1841 blockBox.setToolTipText(rbx.getString("HintBlockEntry")); 1842 break; 1843 case TransitSectionAction.SENSORACTIVE: 1844 case TransitSectionAction.SENSORINACTIVE: 1845 whenSensorComboBox.setVisible(true); 1846 whenSensorComboBox.setToolTipText(rbx.getString("HintSensorEntry")); 1847 break; 1848 case TransitSectionAction.SELECTWHEN: 1849 break; 1850 default: 1851 log.debug("Unhandled transit action code: {}", code); // causes too much noise, no harm done hiding it 1852 } 1853 addEditActionFrame.pack(); 1854 addEditActionFrame.setVisible(true); 1855 } 1856 1857 /** 1858 * Set special stuff depending on What selected, including spinner value. 1859 * 1860 * @param code selected item in getWhatBox 1861 */ 1862 private void setWhat(int code) { 1863 // setting the whatBox here causes recursion 1864 // hide all input boxes, set those needed visible via a switch case 1865 whatStringField.setVisible(false); 1866 whatPercentSpinner.setVisible(false); 1867 whatMinuteSpinner1.setVisible(false); 1868 whatMinuteSpinner2.setVisible(false); 1869 locoFunctionSpinner.setVisible(false); 1870 signalPanel.setVisible(false); 1871 onButton.setVisible(false); 1872 offButton.setVisible(false); 1873 doneSensorLabel.setVisible(false); 1874 doneSensorComboBox.setVisible(false); 1875 panelDelay.setEnabled(true); 1876 panelLoadTrainInfo.setVisible(false); 1877 log.debug("setWhat code = {}", code); 1878 switch (code) { 1879 case TransitSectionAction.TERMINATETRAIN: 1880 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 1881 break; 1882 1883 case TransitSectionAction.LOADTRAININFO: 1884 rosterComboBox.update(); 1885 String[] names = new TrainInfoFile().getTrainInfoFileNames(); 1886 trainInfoComboBox.removeAllItems(); 1887 for (String fn: names) { 1888 trainInfoComboBox.addItem(fn); 1889 if (fn.equals(tWhatString)) { 1890 trainInfoComboBox.setSelectedItem(fn); 1891 } 1892 } 1893 locoAddress.setText(Integer.toString(tWhatData1)); 1894 switch (tWhatData2) { 1895 case TransitSectionAction.LOCOADDRESSTYPEROSTER: 1896 locoAddressRoster.setSelected(true); 1897 setRosterComboBox(rosterComboBox, tWhatString2); 1898 rosterComboBox.setVisible(true); 1899 locoAddress.setVisible(false); 1900 break; 1901 case TransitSectionAction.LOCOADDRESSTYPENUMBER: 1902 locoAddressNumber.setSelected(true); 1903 locoAddress.setText(tWhatString2); 1904 rosterComboBox.setVisible(false); 1905 locoAddress.setVisible(true); 1906 break; 1907 case TransitSectionAction.LOCOADDRESSTYPECURRENT: 1908 locoAddressCurrent.setSelected(true); 1909 locoAddress.setText(""); 1910 rosterComboBox.setVisible(false); 1911 locoAddress.setVisible(false); 1912 break; 1913 case TransitSectionAction.LOCOADDRESSTYPEDEFAULT: 1914 default: 1915 locoAddressDefault.setSelected(true); 1916 rosterComboBox.setVisible(false); 1917 locoAddress.setVisible(false); 1918 locoAddress.setText(""); 1919 break; 1920 } 1921 panelLoadTrainInfo.setVisible(true); 1922 break; 1923 case TransitSectionAction.PAUSE: 1924 if (getWhenMenuCode((String)whenBox.getSelectedItem()) == TransitSectionAction.PRESTARTDELAY) { 1925 panelDelay.setEnabled(false); 1926 } 1927 whatMinuteSpinner1.setModel(new SpinnerNumberModel(1, 1, 65500, 1)); 1928 if (editActionMode) { 1929 whatMinuteSpinner1.setValue(Math.max(curTSA.getDataWhat1(), 1)); 1930 } 1931 whatMinuteSpinner1.setVisible(true); 1932 whatMinuteSpinner1.setToolTipText(rbx.getString("HintPauseData")); 1933 break; 1934 case TransitSectionAction.SETMAXSPEED: 1935 case TransitSectionAction.SETCURRENTSPEED: 1936 case TransitSectionAction.RAMPTRAINSPEED: 1937 if (editActionMode) { 1938 float maxPerc = Math.max(0.01f * curTSA.getDataWhat1(), 0.0f); 1939 whatPercentSpinner.setValue(maxPerc); 1940 } 1941 whatPercentSpinner.setVisible(true); 1942 whatPercentSpinner.setToolTipText(rbx.getString("HintSetSpeedData1")); 1943 break; 1944 case TransitSectionAction.TOMANUALMODE: 1945 if (editActionMode) { 1946 doneSensorComboBox.setSelectedItemByName(curTSA.getStringWhat()); 1947 } 1948 doneSensorLabel.setVisible(true); 1949 doneSensorComboBox.setVisible(true); 1950 doneSensorComboBox.setToolTipText(rbx.getString("HintDoneSensor")); 1951 break; 1952 case TransitSectionAction.SETLIGHT: 1953 onButton.setVisible(true); 1954 offButton.setVisible(true); 1955 onButton.setToolTipText(rbx.getString("HintSetLight")); 1956 offButton.setToolTipText(rbx.getString("HintSetLight")); 1957 break; 1958 case TransitSectionAction.STARTBELL: 1959 break; 1960 case TransitSectionAction.STOPBELL: 1961 break; 1962 case TransitSectionAction.SOUNDHORN: 1963 whatMinuteSpinner1.setValue(100); 1964 whatMinuteSpinner1.setModel(new SpinnerNumberModel(100, 100, 65500, 1)); 1965 if (editActionMode) { 1966 whatMinuteSpinner1.setValue(curTSA.getDataWhat1()); 1967 } 1968 if ((Integer) whatMinuteSpinner1.getValue() < 100) { 1969 whatMinuteSpinner1.setValue(100); // might result from user changing from PAUSE to SOUNDHORN 1970 } 1971 whatMinuteSpinner1.setVisible(true); 1972 whatMinuteSpinner1.setToolTipText(rbx.getString("HintSoundHornData1")); 1973 break; 1974 case TransitSectionAction.SOUNDHORNPATTERN: 1975 whatMinuteSpinner1.setValue(100); 1976 whatMinuteSpinner1.setModel(new SpinnerNumberModel(100, 100, 65500, 1)); 1977 // whatMinuteSpinner2 model never changes 1978 if (editActionMode) { 1979 whatMinuteSpinner1.setValue(curTSA.getDataWhat1()); 1980 whatMinuteSpinner2.setValue(Math.max(curTSA.getDataWhat2(), 100)); 1981 // might result from user changing from sth.else to SOUNDHORNPATTERN 1982 } 1983 if ((Integer) whatMinuteSpinner1.getValue() < 100) { 1984 whatMinuteSpinner1.setValue(100); // might result from user changing from PAUSE to SOUNDHORNPATTERN 1985 } 1986 whatMinuteSpinner1.setVisible(true); 1987 whatMinuteSpinner1.setToolTipText(rbx.getString("HintSoundHornPatternData1")); 1988 whatMinuteSpinner2.setVisible(true); 1989 whatMinuteSpinner2.setToolTipText(rbx.getString("HintSoundHornPatternData2")); 1990 whatStringField.setVisible(true); 1991 break; 1992 case TransitSectionAction.LOCOFUNCTION: 1993 if (editActionMode) { 1994 locoFunctionSpinner.setValue(curTSA.getDataWhat1()); 1995 } 1996 locoFunctionSpinner.setVisible(true); 1997 locoFunctionSpinner.setToolTipText(rbx.getString("HintLocoFunctionData1")); 1998 onButton.setVisible(true); 1999 offButton.setVisible(true); 2000 onButton.setToolTipText(rbx.getString("HintLocoFunctionOnOff")); 2001 offButton.setToolTipText(rbx.getString("HintLocoFunctionOnOff")); 2002 break; 2003 case TransitSectionAction.SETSENSORACTIVE: 2004 case TransitSectionAction.SETSENSORINACTIVE: 2005 if (editActionMode) { 2006 doneSensorComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2007 } 2008 doneSensorComboBox.setVisible(true); 2009 doneSensorComboBox.setToolTipText(rbx.getString("HintSensorEntry")); 2010 break; 2011 case TransitSectionAction.HOLDSIGNAL: 2012 case TransitSectionAction.RELEASESIGNAL: 2013 if (editActionMode) { 2014 SignalMast sm = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(curTSA.getStringWhat()); 2015 if (sm != null) { // name is an existing mast 2016 signalMastComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2017 } else { 2018 SignalHead sh = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(curTSA.getStringWhat()); 2019 if (sh != null) { // name is an existing head 2020 signalHeadComboBox.setSelectedItemByName(curTSA.getStringWhat()); 2021 } 2022 } 2023 } 2024 signalPanel.setVisible(true); 2025 break; 2026 case TransitSectionAction.ESTOP: 2027 default: 2028 log.debug("Unhandled transit section action: {}", code); // causes too much noise, no harm done hiding it 2029 break; 2030 } 2031 addEditActionFrame.pack(); 2032 addEditActionFrame.setVisible(true); 2033 } 2034 2035 private boolean setRosterComboBox(RosterEntryComboBox box, String txt) { 2036 boolean found = false; 2037 for (int i = 1; i < box.getItemCount(); i++) { 2038 if (txt.equals(((RosterEntry) box.getItemAt(i)).getId())) { 2039 box.setSelectedIndex(i); 2040 found = true; 2041 break; 2042 } 2043 } 2044 if (!found && box.getItemCount() > 0) { 2045 box.setSelectedIndex(0); 2046 } 2047 return found; 2048 } 2049 2050 private void updateTrainInfoAddressFields(ActionEvent e) { 2051 if (!((JRadioButton)e.getSource()).isSelected() ) { 2052 return; 2053 } 2054 if (e.getSource() == locoAddressRoster) { 2055 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEROSTER; 2056 rosterComboBox.setVisible(true); 2057 locoAddress.setVisible(false); 2058 } else if (e.getSource() == locoAddressNumber) { 2059 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPENUMBER; 2060 rosterComboBox.setVisible(false); 2061 locoAddress.setVisible(true); 2062 } else if (e.getSource() == locoAddressDefault) { 2063 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEDEFAULT; 2064 rosterComboBox.setVisible(false); 2065 locoAddress.setVisible(false); 2066 } else if (e.getSource() == locoAddressCurrent) { 2067 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPECURRENT; 2068 rosterComboBox.setVisible(false); 2069 locoAddress.setVisible(false); 2070 } else { 2071 log.warn("Unknown button Source"); 2072 } 2073 } 2074 2075 // temporary action variables 2076 private int tWhen = 0; 2077 private int tWhenData = 0; 2078 private String tWhenString = ""; 2079 private int tWhat = 0; 2080 private int tWhatData1 = 0; 2081 private int tWhatData2 = 0; 2082 private String tWhatString = ""; 2083 private String tWhatString2 = ""; 2084 2085 /** 2086 * Handle button presses in Add/Edit Transit Action window. 2087 * 2088 * @param e the event seen 2089 */ 2090 private void createActionPressed(ActionEvent e) { 2091 if ((!validateWhenData()) || (!validateWhatData())) { 2092 return; 2093 } 2094 // entered data is OK, create a special action 2095 curTSA = new TransitSectionAction(tWhen, tWhat, tWhenData, tWhatData1, tWhatData2, tWhenString, tWhatString, tWhatString2); 2096 List<TransitSectionAction> list = action.get(activeRow); 2097 list.add(curTSA); 2098 actionTableModel.fireTableDataChanged(); 2099 addEditActionFrame.setVisible(false); 2100 addEditActionFrame.dispose(); 2101 addEditActionFrame = null; 2102 } 2103 2104 private void updateActionPressed(ActionEvent e) { 2105 if ((!validateWhenData()) || (!validateWhatData())) { 2106 return; 2107 } 2108 // entered data is OK, update the current special action 2109 curTSA.setWhenCode(tWhen); 2110 curTSA.setWhatCode(tWhat); 2111 curTSA.setDataWhen(tWhenData); 2112 curTSA.setDataWhat1(tWhatData1); 2113 curTSA.setDataWhat2(tWhatData2); 2114 curTSA.setStringWhen(tWhenString); 2115 curTSA.setStringWhat(tWhatString); 2116 curTSA.setStringWhat2(tWhatString2); 2117 actionTableModel.fireTableDataChanged(); 2118 addEditActionFrame.setVisible(false); 2119 addEditActionFrame.dispose(); 2120 addEditActionFrame = null; 2121 } 2122 2123 private void cancelAddEditActionPressed(ActionEvent e) { 2124 addEditActionFrame.setVisible(false); 2125 addEditActionFrame.dispose(); 2126 addEditActionFrame = null; 2127 } 2128 2129 private boolean validateWhenData() { 2130 tWhen = getWhenMenuCode((String)whenBox.getSelectedItem()); 2131 tWhenData = (int)whenDataSpinnerInt.getValue(); 2132 tWhenString = ""; 2133 if (tWhen == TransitSectionAction.PRESTARTDELAY ) { 2134 // must have a delay 2135 if (tWhenData <1 ) { 2136 return false; 2137 } 2138 } 2139 if ((tWhen == TransitSectionAction.SENSORACTIVE) || (tWhen == TransitSectionAction.SENSORINACTIVE)) { 2140 if (whenSensorComboBox.getSelectedIndex() != 0) { // it's optional, so might be 0 2141 tWhenString = whenSensorComboBox.getSelectedItemSystemName(); 2142 } 2143 if (!validateSensor(tWhenString, true)) { 2144 return false; 2145 } 2146 } 2147 if ((tWhen == TransitSectionAction.BLOCKENTRY) || (tWhen == TransitSectionAction.BLOCKEXIT)) { 2148 tWhenString = blockList.get(blockBox.getSelectedIndex()).getSystemName(); 2149 } 2150 return true; 2151 } 2152 2153 private boolean validateSensor(String sName, boolean when) { 2154 // check if anything entered 2155 if (sName.length() < 1) { 2156 // no sensor selected 2157 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("NoSensorError")), 2158 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2159 return false; 2160 } 2161 // get the sensor corresponding to this name 2162 Sensor s = InstanceManager.sensorManagerInstance().getSensor(sName); 2163 if (s == null) { 2164 // There is no sensor corresponding to this name 2165 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("SensorEntryError")), 2166 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2167 return false; 2168 } 2169 if (!sName.equals(s.getUserName())) { 2170 if (when) { 2171 tWhenString = sName; 2172 } else { 2173 tWhatString = sName; 2174 } 2175 } 2176 return true; 2177 } 2178 2179 private boolean validateSignal(String sName, boolean when) { 2180 // check if anything is selected 2181 if (sName.length() < 1) { 2182 // no signal selected 2183 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("NoSignalError")), 2184 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2185 return false; 2186 } 2187 // get the signalMast or signalHead corresponding to this name 2188 SignalMast sm = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(sName); 2189 SignalHead sh = null; 2190 if (sm == null) { 2191 sh = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(sName); 2192 } 2193 if (sm == null && sh == null) { 2194 // There is no signal corresponding to this name 2195 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("SignalEntryError")), 2196 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2197 return false; 2198 } 2199 return true; 2200 } 2201 2202 /** 2203 * Validate entered data for selected Action. Converted to use JSpinners 2204 * where applicable, 2017. 2205 * 2206 * @return true if data entered into field whatStringField is valid for selected Action type tWhat 2207 */ 2208 private boolean validateWhatData() { 2209 tWhat = getWhatMenuCode((String)whatBox.getSelectedItem()); 2210 tWhatData1 = 0; 2211 tWhatData2 = 0; 2212 tWhatString = ""; 2213 switch (tWhat) { 2214 case TransitSectionAction.SETMAXSPEED: 2215 case TransitSectionAction.SETCURRENTSPEED: 2216 case TransitSectionAction.RAMPTRAINSPEED: 2217 tWhatData1 = Math.round(100 * (float) whatPercentSpinner.getValue()); 2218 break; 2219 case TransitSectionAction.TOMANUALMODE: 2220 tWhatString=""; 2221 if (doneSensorComboBox.getSelectedIndex() >= 0) { // it's optional, so might be -1 2222 tWhatString = doneSensorComboBox.getSelectedItemSystemName(); // sensor system name 2223 } 2224 if (tWhatString.length() >= 1) { 2225 if (!validateSensor(tWhatString, false)) { 2226 tWhatString = ""; 2227 } 2228 } 2229 break; 2230 case TransitSectionAction.SETLIGHT: 2231 tWhatString = "On"; // NOI18N 2232 if (offButton.isSelected()) { 2233 tWhatString = "Off"; // NOI18N 2234 } 2235 break; 2236 case TransitSectionAction.STARTBELL: 2237 case TransitSectionAction.STOPBELL: 2238 case TransitSectionAction.TERMINATETRAIN: 2239 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2240 break; 2241 case TransitSectionAction.LOADTRAININFO: 2242 if (trainInfoComboBox.getSelectedIndex() < 0 ) { 2243 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingTrainInfoFile")), 2244 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2245 return false; 2246 } 2247 tWhatString = (String)trainInfoComboBox.getSelectedItem(); 2248 if (locoAddressRoster.isSelected()) { 2249 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEROSTER; 2250 // the first item is "select..." 2251 if (rosterComboBox.getSelectedIndex() < 1) { 2252 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingRosterEntryOrLocoAddress")), 2253 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2254 return false; 2255 } 2256 tWhatString2 =((RosterEntry) rosterComboBox.getSelectedItem()).getId(); 2257 } else if (locoAddressNumber.isSelected()) { 2258 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPENUMBER; 2259 tWhatString2 = locoAddress.getText(); 2260 if ((tWhatString2 == null) || tWhatString2.isEmpty() || (tWhatString2.length() < 1)) { 2261 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingRosterEntryOrLocoAddress")), 2262 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2263 return false; 2264 } 2265 } else if (locoAddressDefault.isSelected()) { 2266 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPEDEFAULT; 2267 tWhatString2 = ""; 2268 } else if (locoAddressCurrent.isSelected()) { 2269 tWhatData2 = TransitSectionAction.LOCOADDRESSTYPECURRENT; 2270 tWhatString2 = ""; 2271 } else { 2272 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("UnKnownlocoaddresstype")), 2273 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2274 return false; 2275 } 2276 break; 2277 case TransitSectionAction.PAUSE: 2278 case TransitSectionAction.SOUNDHORN: 2279 tWhatData1 = (Integer) whatMinuteSpinner1.getValue(); 2280 break; 2281 case TransitSectionAction.SOUNDHORNPATTERN: 2282 tWhatData1 = (Integer) whatMinuteSpinner1.getValue(); 2283 tWhatData2 = (Integer) whatMinuteSpinner2.getValue(); 2284 tWhatString = whatStringField.getText(); 2285 if ((tWhatString == null) || tWhatString.isEmpty() || (tWhatString.length() < 1)) { 2286 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("MissingPattern")), 2287 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2288 return false; 2289 } 2290 tWhatString = tWhatString.trim().toLowerCase(); 2291 for (int i = 0; i < tWhatString.length(); i++) { 2292 char c = tWhatString.charAt(i); 2293 if ((c != 's') && (c != 'l')) { 2294 JmriJOptionPane.showMessageDialog(addEditActionFrame, (rbx.getString("ErrorPattern")), 2295 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 2296 return false; 2297 } 2298 } 2299 whatStringField.setText(tWhatString); // re-enter normalized value in display field 2300 break; 2301 case TransitSectionAction.LOCOFUNCTION: 2302 tWhatData1 = (Integer) locoFunctionSpinner.getValue(); 2303 tWhatString = "On"; // NOI18N 2304 if (offButton.isSelected()) { 2305 tWhatString = "Off"; // NOI18N 2306 } 2307 break; 2308 case TransitSectionAction.SETSENSORACTIVE: 2309 case TransitSectionAction.SETSENSORINACTIVE: 2310 if (doneSensorComboBox.getSelectedIndex() > 0) { 2311 tWhatString = doneSensorComboBox.getSelectedItemSystemName(); 2312 } 2313 if (!validateSensor(tWhatString, false)) { 2314 return false; 2315 } 2316 break; 2317 case TransitSectionAction.HOLDSIGNAL: 2318 case TransitSectionAction.RELEASESIGNAL: 2319 if (signalMastComboBox.getSelectedIndex() > 0) { 2320 tWhatString = signalMastComboBox.getSelectedItemSystemName(); 2321 } else if (signalHeadComboBox.getSelectedIndex() > 0) { 2322 tWhatString = signalHeadComboBox.getSelectedItemSystemName(); 2323 } 2324 if (!validateSignal(tWhatString, false)) { 2325 return false; 2326 } 2327 break; 2328 case TransitSectionAction.PRESTARTRESUME: 2329 break; 2330 default: 2331 log.warn("Unhandled transit section action code: {}", tWhat); 2332 break; 2333 } 2334 return true; 2335 } 2336 2337 // initialize combos for add/edit action window 2338 private void initializeWhenBox() { 2339 whenBox.removeAllItems(); 2340 for (int i = 0; i <= TransitSectionAction.NUM_WHENS; i++) { 2341 whenBox.addItem(getWhenMenuText(i)); 2342 } 2343 } 2344 2345 private String getWhenMenuText(int i) { 2346 switch (i) { 2347 case TransitSectionAction.ENTRY: 2348 return rbx.getString("OnEntry"); 2349 case TransitSectionAction.EXIT: 2350 return rbx.getString("OnExit"); 2351 case TransitSectionAction.BLOCKENTRY: 2352 return rbx.getString("OnBlockEntry"); 2353 case TransitSectionAction.BLOCKEXIT: 2354 return rbx.getString("OnBlockExit"); 2355 case TransitSectionAction.TRAINSTOP: 2356 return rbx.getString("TrainStop"); 2357 case TransitSectionAction.TRAINSTART: 2358 return rbx.getString("TrainStart"); 2359 case TransitSectionAction.SENSORACTIVE: 2360 return rbx.getString("OnSensorActive"); 2361 case TransitSectionAction.SENSORINACTIVE: 2362 return rbx.getString("OnSensorInactive"); 2363 case TransitSectionAction.PRESTARTDELAY: 2364 return rbx.getString("PreStartDelay"); 2365 case TransitSectionAction.PRESTARTACTION: 2366 return rbx.getString("PreStartAction"); 2367 case TransitSectionAction.SELECTWHEN: 2368 return rbx.getString("SelectWhen"); 2369 default: 2370 log.warn("Unhandled transit section when code: {}", i); 2371 return rbx.getString("SelectWhen"); 2372 } 2373 } 2374 2375 private int getWhenMenuCode(String s) { 2376 if (s.equals(rbx.getString("OnEntry"))) { 2377 return TransitSectionAction.ENTRY; 2378 } 2379 if (s.equals(rbx.getString("OnExit"))) { 2380 return TransitSectionAction.EXIT; 2381 } 2382 if (s.equals(rbx.getString("OnBlockEntry"))) { 2383 return TransitSectionAction.BLOCKENTRY; 2384 } 2385 if (s.equals(rbx.getString("OnBlockExit"))) { 2386 return TransitSectionAction.BLOCKEXIT; 2387 } 2388 if (s.equals(rbx.getString("TrainStop"))) { 2389 return TransitSectionAction.TRAINSTOP; 2390 } 2391 if (s.equals(rbx.getString("TrainStart"))) { 2392 return TransitSectionAction.TRAINSTART; 2393 } 2394 if (s.equals(rbx.getString("OnSensorActive"))) { 2395 return TransitSectionAction.SENSORACTIVE; 2396 } 2397 if (s.equals(rbx.getString("OnSensorInactive"))) { 2398 return TransitSectionAction.SENSORINACTIVE; 2399 } 2400 if (s.equals(rbx.getString("PreStartDelay"))) { 2401 return TransitSectionAction.PRESTARTDELAY; 2402 } 2403 if (s.equals(rbx.getString("PreStartAction"))) { 2404 return TransitSectionAction.PRESTARTACTION; 2405 } 2406 return TransitSectionAction.SELECTWHEN; 2407 } 2408 2409 private void initializeWhatBox(int code) { 2410 whatBox.removeAllItems(); 2411 List<Integer> excludeCodes = new ArrayList<>(); 2412 List<Integer> includeCodes = new ArrayList<>(); 2413 if (code == TransitSectionAction.PRESTARTACTION) { 2414 // exclude speed changing as that messes up the prestart.List<Section> sectionList = new ArrayList<>(); 2415 excludeCodes = new ArrayList<>(Arrays.asList(TransitSectionAction.SETMAXSPEED, TransitSectionAction.SETCURRENTSPEED, 2416 TransitSectionAction.RAMPTRAINSPEED)); 2417 } else if (code == TransitSectionAction.PRESTARTDELAY) { 2418 includeCodes.add(TransitSectionAction.PRESTARTRESUME); 2419 } else { 2420 excludeCodes.add(TransitSectionAction.PRESTARTRESUME); 2421 } 2422 for (int i = 0; i <= TransitSectionAction.NUM_WHATS; i++) { 2423 if (!excludeCodes.isEmpty()) { 2424 if (! excludeCodes.contains(i)) { 2425 whatBox.addItem(getWhatMenuText(i)); 2426 } 2427 } else if (!includeCodes.isEmpty()) { 2428 if (includeCodes.contains(i)) { 2429 whatBox.addItem(getWhatMenuText(i)); 2430 } 2431 } else { 2432 whatBox.addItem(getWhatMenuText(i)); 2433 } 2434 } 2435 } 2436 2437 @Nonnull 2438 private String getWhatMenuText(int i) { 2439 switch (i) { 2440 case TransitSectionAction.SELECTWHAT: 2441 return rbx.getString("SelectWhat"); 2442 case TransitSectionAction.TERMINATETRAIN: 2443 return rbx.getString("TerminateTrain"); 2444 case TransitSectionAction.LOADTRAININFO: 2445 return rbx.getString("LoadTrainInfo"); 2446 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2447 return rbx.getString("ForcePassNextSafe"); 2448 case TransitSectionAction.PAUSE: 2449 return rbx.getString("Pause"); 2450 case TransitSectionAction.SETMAXSPEED: 2451 return rbx.getString("SetMaxSpeed"); 2452 case TransitSectionAction.SETCURRENTSPEED: 2453 return rbx.getString("SetTrainSpeed"); 2454 case TransitSectionAction.RAMPTRAINSPEED: 2455 return rbx.getString("RampTrainSpeed"); 2456 case TransitSectionAction.TOMANUALMODE: 2457 return rbx.getString("ToManualMode"); 2458 case TransitSectionAction.SETLIGHT: 2459 return rbx.getString("SetLight"); 2460 case TransitSectionAction.STARTBELL: 2461 return rbx.getString("StartBell"); 2462 case TransitSectionAction.STOPBELL: 2463 return rbx.getString("StopBell"); 2464 case TransitSectionAction.SOUNDHORN: 2465 return rbx.getString("SoundHorn"); 2466 case TransitSectionAction.SOUNDHORNPATTERN: 2467 return rbx.getString("SoundHornPattern"); 2468 case TransitSectionAction.LOCOFUNCTION: 2469 return rbx.getString("LocoFunction"); 2470 case TransitSectionAction.SETSENSORACTIVE: 2471 return rbx.getString("SetSensorActive"); 2472 case TransitSectionAction.SETSENSORINACTIVE: 2473 return rbx.getString("SetSensorInactive"); 2474 case TransitSectionAction.HOLDSIGNAL: 2475 return rbx.getString("HoldSignal"); 2476 case TransitSectionAction.RELEASESIGNAL: 2477 return rbx.getString("ReleaseSignal"); 2478 case TransitSectionAction.ESTOP: 2479 return rbx.getString("EStop"); 2480 case TransitSectionAction.PRESTARTRESUME: 2481 return rbx.getString("PreStartResume"); 2482 default: 2483 log.warn("Unhandled transit section action code: {}", i); 2484 return rbx.getString("SelectWhat"); 2485 } 2486 } 2487 2488 private int getWhatMenuCode(@Nonnull String s) { 2489 if (s.equals(rbx.getString("SelectWhat"))) { 2490 return TransitSectionAction.SELECTWHAT; 2491 } 2492 if (s.equals(rbx.getString("TerminateTrain"))) { 2493 return TransitSectionAction.TERMINATETRAIN; 2494 } 2495 if (s.equals(rbx.getString("ForcePassNextSafe"))) { 2496 return TransitSectionAction.FORCEALLOCATEPASSSAFESECTION; 2497 } 2498 if (s.equals(rbx.getString("LoadTrainInfo"))) { 2499 return TransitSectionAction.LOADTRAININFO; 2500 } 2501 if (s.equals(rbx.getString("Pause"))) { 2502 return TransitSectionAction.PAUSE; 2503 } 2504 if (s.equals(rbx.getString("SetMaxSpeed"))) { 2505 return TransitSectionAction.SETMAXSPEED; 2506 } 2507 if (s.equals(rbx.getString("SetTrainSpeed"))) { 2508 return TransitSectionAction.SETCURRENTSPEED; 2509 } 2510 if (s.equals(rbx.getString("RampTrainSpeed"))) { 2511 return TransitSectionAction.RAMPTRAINSPEED; 2512 } 2513 if (s.equals(rbx.getString("ToManualMode"))) { 2514 return TransitSectionAction.TOMANUALMODE; 2515 } 2516 if (s.equals(rbx.getString("SetLight"))) { 2517 return TransitSectionAction.SETLIGHT; 2518 } 2519 if (s.equals(rbx.getString("StartBell"))) { 2520 return TransitSectionAction.STARTBELL; 2521 } 2522 if (s.equals(rbx.getString("StopBell"))) { 2523 return TransitSectionAction.STOPBELL; 2524 } 2525 if (s.equals(rbx.getString("SoundHorn"))) { 2526 return TransitSectionAction.SOUNDHORN; 2527 } 2528 if (s.equals(rbx.getString("SoundHornPattern"))) { 2529 return TransitSectionAction.SOUNDHORNPATTERN; 2530 } 2531 if (s.equals(rbx.getString("LocoFunction"))) { 2532 return TransitSectionAction.LOCOFUNCTION; 2533 } 2534 if (s.equals(rbx.getString("SetSensorActive"))) { 2535 return TransitSectionAction.SETSENSORACTIVE; 2536 } 2537 if (s.equals(rbx.getString("SetSensorInactive"))) { 2538 return TransitSectionAction.SETSENSORINACTIVE; 2539 } 2540 if (s.equals(rbx.getString("HoldSignal"))) { 2541 return TransitSectionAction.HOLDSIGNAL; 2542 } 2543 if (s.equals(rbx.getString("ReleaseSignal"))) { 2544 return TransitSectionAction.RELEASESIGNAL; 2545 } 2546 if (s.equals(rbx.getString("EStop"))) { 2547 return TransitSectionAction.ESTOP; 2548 } 2549 if (s.equals(rbx.getString("PreStartResume"))) { 2550 return TransitSectionAction.PRESTARTRESUME; 2551 } 2552 log.warn("Unhandled transit section action text: {}", s); 2553 return 0; 2554 } 2555 2556 private void initializeBlockBox() { 2557 blockList = sectionList.get(activeRow).getBlockList(); 2558 blockBox.removeAllItems(); 2559 for (int i = 0; i < blockList.size(); i++) { 2560 String s = blockList.get(i).getDisplayName(); 2561 blockBox.addItem(s); 2562 } 2563 } 2564 2565 private void setBlockBox() { 2566 if (editActionMode) { 2567 if ((curTSA.getWhenCode() == TransitSectionAction.BLOCKENTRY) 2568 || (curTSA.getWhenCode() == TransitSectionAction.BLOCKEXIT)) { 2569 // assumes that initializeBlockBox has been called prior to this call 2570 for (int i = 0; i < blockList.size(); i++) { 2571 if (curTSA.getStringWhen().equals(blockList.get(i).getSystemName())) { 2572 blockBox.setSelectedIndex(i); 2573 return; 2574 } 2575 } 2576 } 2577 } 2578 blockBox.setSelectedIndex(0); 2579 } 2580 2581 private void editAction(int r) { 2582 curTSA = action.get(activeRow).get(r); 2583 editActionMode = true; 2584 addEditActionWindow(); 2585 } 2586 2587 private void deleteAction(int r) { 2588 TransitSectionAction tsa = action.get(activeRow).get(r); 2589 action.get(activeRow).remove(r); 2590 tsa.dispose(); 2591 actionTableModel.fireTableDataChanged(); 2592 } 2593 2594 /** 2595 * Build display When string for Actions table. 2596 * 2597 * @param r row in the Special Actions table. A TransitSectionAction must be 2598 * available for this row. 2599 * @return display string including entered values 2600 */ 2601 private String getWhenText(int r) { 2602 TransitSectionAction tsa = action.get(activeRow).get(r); 2603 switch (tsa.getWhenCode()) { 2604 case TransitSectionAction.ENTRY: 2605 if (tsa.getDataWhen() > 0) { 2606 return java.text.MessageFormat.format(rbx.getString("OnEntryDelayedFull"), 2607 new Object[]{"" + tsa.getDataWhen()}); 2608 } 2609 return rbx.getString("OnEntryFull"); 2610 case TransitSectionAction.EXIT: 2611 if (tsa.getDataWhen() > 0) { 2612 return java.text.MessageFormat.format(rbx.getString("OnExitDelayedFull"), 2613 new Object[]{"" + tsa.getDataWhen()}); 2614 } 2615 return rbx.getString("OnExitFull"); 2616 case TransitSectionAction.BLOCKENTRY: 2617 if (tsa.getDataWhen() > 0) { 2618 return java.text.MessageFormat.format(rbx.getString("OnBlockEntryDelayedFull"), 2619 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2620 } 2621 return java.text.MessageFormat.format(rbx.getString("OnBlockEntryFull"), 2622 new Object[]{tsa.getStringWhen()}); 2623 case TransitSectionAction.BLOCKEXIT: 2624 if (tsa.getDataWhen() > 0) { 2625 return java.text.MessageFormat.format(rbx.getString("OnBlockExitDelayedFull"), 2626 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2627 } 2628 return java.text.MessageFormat.format(rbx.getString("OnBlockExitFull"), 2629 new Object[]{tsa.getStringWhen()}); 2630 case TransitSectionAction.TRAINSTOP: 2631 if (tsa.getDataWhen() > 0) { 2632 return java.text.MessageFormat.format(rbx.getString("TrainStopDelayedFull"), 2633 new Object[]{"" + tsa.getDataWhen()}); 2634 } 2635 return rbx.getString("TrainStopFull"); 2636 case TransitSectionAction.TRAINSTART: 2637 if (tsa.getDataWhen() > 0) { 2638 return java.text.MessageFormat.format(rbx.getString("TrainStartDelayedFull"), 2639 new Object[]{"" + tsa.getDataWhen()}); 2640 } 2641 return rbx.getString("TrainStartFull"); 2642 case TransitSectionAction.SENSORACTIVE: 2643 if (tsa.getDataWhen() > 0) { 2644 return java.text.MessageFormat.format(rbx.getString("OnSensorActiveDelayedFull"), 2645 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2646 } 2647 return java.text.MessageFormat.format(rbx.getString("OnSensorActiveFull"), 2648 new Object[]{tsa.getStringWhen()}); 2649 case TransitSectionAction.SENSORINACTIVE: 2650 if (tsa.getDataWhen() > 0) { 2651 return java.text.MessageFormat.format(rbx.getString("OnSensorInactiveDelayedFull"), 2652 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2653 } 2654 return java.text.MessageFormat.format(rbx.getString("OnSensorInactiveFull"), 2655 new Object[]{tsa.getStringWhen()}); 2656 case TransitSectionAction.PRESTARTDELAY: 2657 return java.text.MessageFormat.format(rbx.getString("PreStartDelayFull"), 2658 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2659 case TransitSectionAction.PRESTARTACTION: 2660 return java.text.MessageFormat.format(rbx.getString("PreStartActionFull"), 2661 new Object[]{"" + tsa.getDataWhen(), tsa.getStringWhen()}); 2662 default: 2663 log.warn("Unhandled transit section action When code: {}",tsa.getWhenCode()); 2664 return(""); 2665 } 2666 } 2667 2668 /** 2669 * Build display What string for Actions table. 2670 * 2671 * @param r row in the Special Actions table. A TransitSectionAction must be 2672 * available for this row. 2673 * @return display string including entered values 2674 */ 2675 private String getWhatText(int r) { 2676 TransitSectionAction tsa = action.get(activeRow).get(r); 2677 switch (tsa.getWhatCode()) { 2678 case TransitSectionAction.PAUSE: 2679 return java.text.MessageFormat.format(rbx.getString("PauseFull"), 2680 new Object[]{tsa.getDataWhat1()}); 2681 case TransitSectionAction.SETMAXSPEED: 2682 return java.text.MessageFormat.format(rbx.getString("SetMaxSpeedFull"), 2683 new Object[]{tsa.getDataWhat1()}); 2684 case TransitSectionAction.SETCURRENTSPEED: 2685 return java.text.MessageFormat.format(rbx.getString("SetTrainSpeedFull"), 2686 new Object[]{tsa.getDataWhat1()}); 2687 case TransitSectionAction.RAMPTRAINSPEED: 2688 return java.text.MessageFormat.format(rbx.getString("RampTrainSpeedFull"), 2689 new Object[]{"" + tsa.getDataWhat1()}); 2690 case TransitSectionAction.TOMANUALMODE: 2691 if (tsa.getStringWhat().length() > 0) { 2692 return java.text.MessageFormat.format(rbx.getString("ToManualModeAltFull"), 2693 new Object[]{tsa.getStringWhat()}); 2694 } 2695 return rbx.getString("ToManualModeFull"); 2696 case TransitSectionAction.SETLIGHT: 2697 if (tsa.getStringWhat().equals("Off")) { 2698 return java.text.MessageFormat.format(rbx.getString("SetLightFull"), 2699 new Object[]{Bundle.getMessage("StateOff")}); 2700 } 2701 return java.text.MessageFormat.format(rbx.getString("SetLightFull"), 2702 new Object[]{Bundle.getMessage("StateOn")}); 2703 case TransitSectionAction.STARTBELL: 2704 return rbx.getString("StartBellFull"); 2705 case TransitSectionAction.STOPBELL: 2706 return rbx.getString("StopBellFull"); 2707 case TransitSectionAction.SOUNDHORN: 2708 return java.text.MessageFormat.format(rbx.getString("SoundHornFull"), 2709 new Object[]{tsa.getDataWhat1()}); 2710 case TransitSectionAction.SOUNDHORNPATTERN: 2711 return java.text.MessageFormat.format(rbx.getString("SoundHornPatternFull"), 2712 new Object[]{tsa.getStringWhat(), "" + tsa.getDataWhat1(), "" + tsa.getDataWhat2()}); 2713 case TransitSectionAction.LOCOFUNCTION: 2714 if (tsa.getStringWhat().equals("Off")) { 2715 return java.text.MessageFormat.format(rbx.getString("LocoFunctionFull"), 2716 new Object[]{"" + tsa.getDataWhat1(), Bundle.getMessage("StateOff")}); 2717 } 2718 return java.text.MessageFormat.format(rbx.getString("LocoFunctionFull"), 2719 new Object[]{"" + tsa.getDataWhat1(), Bundle.getMessage("StateOn")}); 2720 case TransitSectionAction.SETSENSORACTIVE: 2721 return java.text.MessageFormat.format(rbx.getString("SetSensorActiveFull"), 2722 new Object[]{tsa.getStringWhat()}); 2723 case TransitSectionAction.SETSENSORINACTIVE: 2724 return java.text.MessageFormat.format(rbx.getString("SetSensorInactiveFull"), 2725 new Object[]{tsa.getStringWhat()}); 2726 case TransitSectionAction.HOLDSIGNAL: 2727 return java.text.MessageFormat.format(rbx.getString("HoldSignalFull"), 2728 new Object[]{tsa.getStringWhat()}); 2729 case TransitSectionAction.RELEASESIGNAL: 2730 return java.text.MessageFormat.format(rbx.getString("ReleaseSignalFull"), 2731 new Object[]{tsa.getStringWhat()}); 2732 case TransitSectionAction.PRESTARTRESUME: 2733 return java.text.MessageFormat.format(rbx.getString("PreStartResumeFull"), 2734 new Object[]{tsa.getDataWhen()}); 2735 case TransitSectionAction.ESTOP: 2736 return rbx.getString("EStopFull"); 2737 case TransitSectionAction.TERMINATETRAIN: 2738 return rbx.getString("TerminateTrain"); 2739 case TransitSectionAction.FORCEALLOCATEPASSSAFESECTION: 2740 return rbx.getString("ForcePassNextSafe"); 2741 case TransitSectionAction.LOADTRAININFO: 2742 switch (tsa.getDataWhat2()) { 2743 case TransitSectionAction.LOCOADDRESSTYPEROSTER: 2744 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoRosterFull"), 2745 new Object[]{tsa.getStringWhat(),tsa.getStringWhat2()}); 2746 case TransitSectionAction.LOCOADDRESSTYPENUMBER: 2747 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoNumberFull"), 2748 new Object[]{tsa.getStringWhat(),tsa.getStringWhat2()}); 2749 case TransitSectionAction.LOCOADDRESSTYPECURRENT: 2750 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoCurrentFull"), 2751 new Object[]{tsa.getStringWhat()}); 2752 case TransitSectionAction.LOCOADDRESSTYPEDEFAULT: 2753 default: 2754 return java.text.MessageFormat.format(rbx.getString("LoadTrainInfoDefaultFull"), 2755 new Object[]{tsa.getStringWhat()}); 2756 } 2757 case TransitSectionAction.SELECTWHAT: 2758 return rbx.getString("SelectWhat"); 2759 default: 2760 log.warn("Unhandled transit section action What code: {}", tsa.getWhatCode()); 2761 break; 2762 } 2763 return "WHAT"; 2764 } 2765 2766 private String getSectionNameByRow(int r) { 2767 return sectionList.get(r).getDisplayName(); 2768 } 2769 2770 /** 2771 * Table model for Sections in Create/Edit Transit window. 2772 */ 2773 public class SectionTableModel extends javax.swing.table.AbstractTableModel implements 2774 java.beans.PropertyChangeListener { 2775 2776 public static final int SEQUENCE_COLUMN = 0; 2777 public static final int SECTIONNAME_COLUMN = 1; 2778 public static final int ACTION_COLUMN = 2; 2779 public static final int SEC_DIRECTION_COLUMN = 3; 2780 public static final int ALTERNATE_COLUMN = 4; 2781 public static final int SAFE_COLUMN = 5; 2782 public static final int STOPALLOCATING_SENSOR = 6; 2783 public static final int FWD_STOPPING_LENGTH = 7; 2784 public static final int REV_STOPPING_LENGTH = 8; 2785 public static final int NUMBER_OF_COLUMNS = 9; 2786 2787 public SectionTableModel() { 2788 super(); 2789 addPcl(); 2790 } 2791 2792 final void addPcl(){ 2793 sectionManager.addPropertyChangeListener(this); 2794 } 2795 2796 @Override 2797 public void propertyChange(java.beans.PropertyChangeEvent e) { 2798 if (Manager.PROPERTY_LENGTH.equals(e.getPropertyName())) { 2799 // a new NamedBean is available in the manager 2800 fireTableDataChanged(); 2801 } 2802 if (e.getSource() instanceof SensorManager 2803 && SensorManager.PROPERTY_DISPLAY_LIST_NAME.equals(e.getPropertyName())) { 2804 updateSensorList(); 2805 } 2806 } 2807 2808 @Override 2809 public Class<?> getColumnClass(int c) { 2810 switch (c) { 2811 case ACTION_COLUMN: 2812 return JButton.class; 2813 case SAFE_COLUMN: 2814 return Boolean.class; 2815 case STOPALLOCATING_SENSOR: 2816 return JComboBox.class; 2817 case FWD_STOPPING_LENGTH: 2818 case REV_STOPPING_LENGTH: 2819 return JSpinner.class; 2820 default: 2821 return super.getColumnClass(c); 2822 } 2823 } 2824 2825 @Override 2826 public int getColumnCount() { 2827 return NUMBER_OF_COLUMNS; 2828 } 2829 2830 @Override 2831 public int getRowCount() { 2832 return (sectionList.size()); 2833 } 2834 2835 @Override 2836 public boolean isCellEditable(int r, int c) { 2837 switch (c) { 2838 case ACTION_COLUMN: 2839 case SAFE_COLUMN: 2840 case STOPALLOCATING_SENSOR: 2841 case FWD_STOPPING_LENGTH: 2842 case REV_STOPPING_LENGTH: 2843 return true; 2844 default: 2845 return false; 2846 } 2847 } 2848 2849 @Override 2850 public String getColumnName(int col) { 2851 switch (col) { 2852 case SEQUENCE_COLUMN: 2853 return rbx.getString("SequenceColName"); 2854 case SECTIONNAME_COLUMN: 2855 return Bundle.getMessage("BeanNameSection"); 2856 case ACTION_COLUMN: 2857 return rbx.getString("ActionColName"); 2858 case SEC_DIRECTION_COLUMN: 2859 return rbx.getString("DirectionColName"); 2860 case ALTERNATE_COLUMN: 2861 return rbx.getString("AlternateColName"); 2862 case SAFE_COLUMN: 2863 return rbx.getString("SafeColName"); 2864 case STOPALLOCATING_SENSOR: 2865 return rbx.getString("StopAllocationColName"); 2866 case FWD_STOPPING_LENGTH: 2867 return rbx.getString("FwdStopDistance"); 2868 case REV_STOPPING_LENGTH: 2869 return rbx.getString("RevStopDistance"); 2870 default: 2871 return ""; 2872 } 2873 } 2874 2875 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DB_DUPLICATE_SWITCH_CLAUSES", 2876 justification="better to keep cases in column order rather than to combine") 2877 public int getPreferredWidth(int col) { 2878 switch (col) { 2879 case SEQUENCE_COLUMN: 2880 return new JTextField(8).getPreferredSize().width; 2881 case SECTIONNAME_COLUMN: 2882 return new JTextField(17).getPreferredSize().width; 2883 case ACTION_COLUMN: 2884 return new JTextField(12).getPreferredSize().width; 2885 case SEC_DIRECTION_COLUMN: 2886 return new JTextField(12).getPreferredSize().width; 2887 case ALTERNATE_COLUMN: 2888 return new JTextField(12).getPreferredSize().width; 2889 case SAFE_COLUMN: 2890 return new JTextField(4).getPreferredSize().width; 2891 case STOPALLOCATING_SENSOR: 2892 return new JTextField(12).getPreferredSize().width; 2893 case FWD_STOPPING_LENGTH: 2894 return new JTextField(12).getPreferredSize().width; 2895 case REV_STOPPING_LENGTH: 2896 return new JTextField(12).getPreferredSize().width; 2897 default: 2898 // fall through 2899 break; 2900 } 2901 return new JTextField(5).getPreferredSize().width; 2902 } 2903 2904 @Override 2905 public Object getValueAt(int r, int c) { 2906 int rx = r; 2907 if (rx > sectionList.size()) { 2908 return null; 2909 } 2910 switch (c) { 2911 case SEQUENCE_COLUMN: 2912 return ("" + sequence.get(rx)); 2913 case SECTIONNAME_COLUMN: 2914 return (getSectionNameByRow(rx)); 2915 case ACTION_COLUMN: 2916 return rbx.getString("AddEditActions"); 2917 case SEC_DIRECTION_COLUMN: 2918 if (direction.get(rx) == Section.FORWARD) { 2919 return rbx.getString("SectionForward"); 2920 } else if (direction.get(rx) == Section.REVERSE) { 2921 return rbx.getString("SectionReverse"); 2922 } 2923 return Bundle.getMessage("BeanStateUnknown"); 2924 case ALTERNATE_COLUMN: 2925 if (alternate.get(rx)) { 2926 return rbx.getString("Alternate"); 2927 } 2928 return rbx.getString("Primary"); 2929 case SAFE_COLUMN: 2930 return safe.get(rx); 2931 case STOPALLOCATING_SENSOR: 2932 String sensor = sensorStopAllocation.get(rx); 2933 JComboBox<String> cb = new JComboBox<>(sensorList); 2934 JComboBoxUtil.setupComboBoxMaxRows(cb); 2935 String name = (sensor != null) ? sensor : ""; 2936 cb.setSelectedItem(name); 2937 return cb; 2938 case FWD_STOPPING_LENGTH: 2939 JSpinner jf = new JSpinner(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.0f), Float.valueOf(2.0f), Float.valueOf(0.05f))); 2940 jf.setEditor(new JSpinner.NumberEditor(jf, "##0.0# %")); 2941 jf.setValue(fwdStopPerCent.get(rx)); 2942 return jf; 2943 case REV_STOPPING_LENGTH: 2944 JSpinner jr = new JSpinner(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.0f), Float.valueOf(2.0f), Float.valueOf(0.05f))); 2945 jr.setEditor(new JSpinner.NumberEditor(jr, "##0.0# %")); 2946 jr.setValue(revStopPerCent.get(rx)); 2947 return jr; 2948 default: 2949 return Bundle.getMessage("BeanStateUnknown"); 2950 } 2951 } 2952 2953 @Override 2954 public void setValueAt(Object value, int row, int col) { 2955 switch (col) { 2956 case ACTION_COLUMN: 2957 addEditActionsPressed(row); 2958 break; 2959 case SAFE_COLUMN: 2960 boolean val = ((Boolean) value); 2961 safe.set(row, val); // use checkbox to show Safe 2962 break; 2963 case STOPALLOCATING_SENSOR: 2964 JComboBox<?> cb = (JComboBox<?>) value; 2965 if (cb.getSelectedIndex() < 0) { 2966 sensorStopAllocation.set(row, ""); 2967 } else { 2968 sensorStopAllocation.set(row, (String) cb.getSelectedItem()); 2969 } 2970 break; 2971 case FWD_STOPPING_LENGTH: 2972 fwdStopPerCent.set(row, (Float)value); 2973 break; 2974 case REV_STOPPING_LENGTH: 2975 revStopPerCent.set(row, (Float)value); 2976 break; 2977 default: 2978 break; 2979 } 2980 } 2981 2982 public void dispose(){ 2983 sectionManager.removePropertyChangeListener(this); 2984 } 2985 } 2986 2987 private void updateSensorList() { 2988 Set<Sensor> nameSet = InstanceManager.getDefault(SensorManager.class).getNamedBeanSet(); 2989 String[] displayList = new String[nameSet.size()]; 2990 int i = 0; 2991 for (Sensor nBean : nameSet) { 2992 if (nBean != null) { 2993 displayList[i++] = nBean.getDisplayName(); 2994 } 2995 } 2996 java.util.Arrays.sort(displayList, new jmri.util.AlphanumComparator()); 2997 sensorList = new String[displayList.length + 1]; 2998 sensorList[0] = ""; 2999 i = 1; 3000 for (String name : displayList) { 3001 sensorList[i] = name; 3002 i++; 3003 } 3004 } 3005 3006 3007 /** 3008 * Table model for Actions in Special Actions window. Currently shows max. 5 3009 * rows. 3010 */ 3011 public class SpecialActionTableModel extends javax.swing.table.AbstractTableModel implements 3012 java.beans.PropertyChangeListener { 3013 3014 public static final int WHEN_COLUMN = 0; 3015 public static final int WHAT_COLUMN = 1; 3016 public static final int EDIT_COLUMN = 2; 3017 public static final int REMOVE_COLUMN = 3; 3018 3019 public SpecialActionTableModel() { 3020 super(); 3021 addPcl(); 3022 } 3023 3024 final void addPcl(){ 3025 sectionManager.addPropertyChangeListener(this); 3026 } 3027 3028 @Override 3029 public void propertyChange(java.beans.PropertyChangeEvent e) { 3030 if ( Manager.PROPERTY_LENGTH.equals(e.getPropertyName())) { 3031 // a new NamedBean is available in the manager 3032 fireTableDataChanged(); 3033 } 3034 } 3035 3036 @Override 3037 public Class<?> getColumnClass(int c) { 3038 switch (c) { 3039 case EDIT_COLUMN: 3040 case REMOVE_COLUMN: 3041 return JButton.class; 3042 case WHEN_COLUMN: 3043 case WHAT_COLUMN: 3044 default: 3045 return String.class; 3046 } 3047 } 3048 3049 @Override 3050 public int getColumnCount() { 3051 return REMOVE_COLUMN + 1; 3052 } 3053 3054 @Override 3055 public int getRowCount() { 3056 return (action.get(activeRow).size()); 3057 } 3058 3059 @Override 3060 public boolean isCellEditable(int r, int c) { 3061 switch (c) { 3062 case EDIT_COLUMN: 3063 case REMOVE_COLUMN: 3064 return true; 3065 default: 3066 return false; 3067 } 3068 } 3069 3070 @Override 3071 public String getColumnName(int col) { 3072 switch (col) { 3073 case WHEN_COLUMN: 3074 return rbx.getString("WhenColName"); 3075 case WHAT_COLUMN: 3076 return rbx.getString("WhatColName"); 3077 default: 3078 return ""; 3079 } 3080 } 3081 3082 public int getPreferredWidth(int col) { 3083 switch (col) { 3084 case WHEN_COLUMN: 3085 case WHAT_COLUMN: 3086 return new JTextField(50).getPreferredSize().width; 3087 case EDIT_COLUMN: 3088 case REMOVE_COLUMN: 3089 default: 3090 return new JTextField(8).getPreferredSize().width; 3091 } 3092 } 3093 3094 @Override 3095 public Object getValueAt(int r, int c) { 3096 int rx = r; 3097 if (rx > action.get(activeRow).size()) { 3098 return null; 3099 } 3100 switch (c) { 3101 case WHEN_COLUMN: 3102 return (getWhenText(rx)); 3103 case WHAT_COLUMN: 3104 return (getWhatText(rx)); 3105 case EDIT_COLUMN: 3106 return Bundle.getMessage("ButtonEdit"); 3107 case REMOVE_COLUMN: 3108 return Bundle.getMessage("ButtonDelete"); 3109 default: 3110 return Bundle.getMessage("BeanStateUnknown"); // normally not in use 3111 } 3112 } 3113 3114 @Override 3115 public void setValueAt(Object value, int row, int col) { 3116 if (col == EDIT_COLUMN) { 3117 // set up to edit 3118 editAction(row); 3119 } 3120 else if (col == REMOVE_COLUMN) { 3121 deleteAction(row); 3122 } 3123 } 3124 3125 public void dispose(){ 3126 sectionManager.removePropertyChangeListener(this); 3127 } 3128 } 3129 3130 @Override 3131 protected String getClassName() { 3132 return TransitTableAction.class.getName(); 3133 } 3134 3135 @Override 3136 public String getClassDescription() { 3137 return Bundle.getMessage("TitleTransitTable"); 3138 } 3139 3140 public class JSpinnerCellRenderer extends DefaultTableCellRenderer { 3141 3142 public JSpinnerCellRenderer() { 3143 } 3144 3145 @Override 3146 public Component getTableCellRendererComponent(JTable table, Object value, 3147 boolean isSelected, boolean hasFocus, 3148 int row, int column) { 3149 if (value instanceof JSpinner) { 3150 switch (column) { 3151 case SectionTableModel.FWD_STOPPING_LENGTH: 3152 ((JSpinner) value).setValue(fwdStopPerCent.get(row)); 3153 break; 3154 case SectionTableModel.REV_STOPPING_LENGTH: 3155 ((JSpinner) value).setValue(revStopPerCent.get(row)); 3156 break; 3157 default: 3158 log.error("getTableCellEditorComponent col[{}] is bad.",column); 3159 } 3160 } 3161 return (Component)value; 3162 } 3163 } 3164 3165 public class JSpinnerCellEditor extends AbstractCellEditor implements TableCellEditor { 3166 private JSpinner spinner; 3167 3168 public JSpinnerCellEditor() { 3169 } 3170 3171 @Override 3172 public Component getTableCellEditorComponent(JTable table, Object value, 3173 boolean isSelected, int row, int column) { 3174 spinner = (JSpinner) value; 3175 if (value instanceof JSpinner) { 3176 switch (column) { 3177 case SectionTableModel.FWD_STOPPING_LENGTH: 3178 ((JSpinner) value).setValue(fwdStopPerCent.get(row)); 3179 break; 3180 case SectionTableModel.REV_STOPPING_LENGTH: 3181 ((JSpinner) value).setValue(revStopPerCent.get(row)); 3182 break; 3183 default: 3184 log.error("getTableCellEditorComponent col[{}] is bad.",column); 3185 } 3186 } 3187 return (Component)value; 3188 } 3189 3190 @Override 3191 public Object getCellEditorValue() { 3192 return spinner.getValue(); 3193 } 3194 } 3195 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TransitTableAction.class); 3196 3197}