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