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