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