001package jmri.jmrit.dispatcher; 002 003import java.awt.Container; 004import java.awt.FlowLayout; 005import java.awt.event.ActionEvent; 006import java.awt.event.ActionListener; 007import java.awt.event.ItemEvent; 008import java.awt.event.ItemListener; 009import java.util.ArrayList; 010import java.util.HashSet; 011import java.util.List; 012import java.util.Set; 013 014import javax.swing.BorderFactory; 015import javax.swing.BoxLayout; 016import javax.swing.ButtonGroup; 017import javax.swing.JButton; 018import javax.swing.JCheckBox; 019import javax.swing.JComboBox; 020import javax.swing.JLabel; 021import javax.swing.JPanel; 022import javax.swing.JRadioButton; 023import javax.swing.JScrollPane; 024import javax.swing.JSeparator; 025import javax.swing.JSpinner; 026import javax.swing.JTextField; 027import javax.swing.SpinnerNumberModel; 028 029import jmri.Block; 030import jmri.InstanceManager; 031import jmri.Sensor; 032import jmri.Transit; 033import jmri.TransitManager; 034import jmri.jmrit.dispatcher.ActiveTrain.TrainDetection; 035import jmri.jmrit.dispatcher.DispatcherFrame.TrainsFrom; 036import jmri.jmrit.operations.trains.Train; 037import jmri.jmrit.operations.trains.TrainManager; 038import jmri.jmrit.roster.Roster; 039import jmri.jmrit.roster.RosterEntry; 040import jmri.jmrit.roster.swing.RosterEntryComboBox; 041import jmri.swing.NamedBeanComboBox; 042import jmri.util.JmriJFrame; 043import jmri.util.swing.JComboBoxUtil; 044import jmri.util.swing.JmriJOptionPane; 045 046/** 047 * Displays the Activate New Train dialog and processes information entered 048 * there. 049 * <p> 050 * This module works with Dispatcher, which initiates the display of the dialog. 051 * Dispatcher also creates the ActiveTrain. 052 * <p> 053 * This file is part of JMRI. 054 * <p> 055 * JMRI is open source software; you can redistribute it and/or modify it under 056 * the terms of version 2 of the GNU General Public License as published by the 057 * Free Software Foundation. See the "COPYING" file for a copy of this license. 058 * <p> 059 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 060 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 061 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 062 * 063 * @author Dave Duchamp Copyright (C) 2009 064 */ 065public class ActivateTrainFrame extends JmriJFrame { 066 067 public ActivateTrainFrame(DispatcherFrame d) { 068 super(true,true); 069 _dispatcher = d; 070 _tiFile = new TrainInfoFile(); 071 } 072 073 // operational instance variables 074 private DispatcherFrame _dispatcher = null; 075 private TrainInfoFile _tiFile = null; 076 private TrainsFrom _TrainsFrom; 077 private List<ActiveTrain> _ActiveTrainsList = null; 078 private final TransitManager _TransitManager = InstanceManager.getDefault(jmri.TransitManager.class); 079 private String _trainInfoName = ""; 080 081 // initiate train window variables 082 private Transit selectedTransit = null; 083 //private String selectedTrain = ""; 084 private JmriJFrame initiateFrame = null; 085 private Container initiatePane = null; 086 private final jmri.swing.NamedBeanComboBox<Transit> transitSelectBox = new jmri.swing.NamedBeanComboBox<>(_TransitManager); 087 private final JLabel trainBoxLabel = new JLabel(" " + Bundle.getMessage("TrainBoxLabel") + ":"); 088 private final JComboBox<Object> trainSelectBox = new JComboBox<>(); 089 // private final List<RosterEntry> trainBoxList = new ArrayList<>(); 090 private RosterEntryComboBox rosterComboBox = null; 091 private final JLabel trainFieldLabel = new JLabel(Bundle.getMessage("TrainBoxLabel") + ":"); 092 private final JTextField trainNameField = new JTextField(10); 093 private final JLabel dccAddressFieldLabel = new JLabel(" " + Bundle.getMessage("DccAddressFieldLabel") + ":"); 094 private final JSpinner dccAddressSpinner = new JSpinner(new SpinnerNumberModel(3, 1, 9999, 1)); 095 private final JCheckBox inTransitBox = new JCheckBox(Bundle.getMessage("TrainInTransit")); 096 private final JComboBox<String> startingBlockBox = new JComboBox<>(); 097 private List<Block> startingBlockBoxList = new ArrayList<>(); 098 private List<Integer> startingBlockSeqList = new ArrayList<>(); 099 private final JComboBox<String> destinationBlockBox = new JComboBox<>(); 100 private List<Block> destinationBlockBoxList = new ArrayList<>(); 101 private List<Integer> destinationBlockSeqList = new ArrayList<>(); 102 private JButton addNewTrainButton = null; 103 private JButton loadButton = null; 104 private JButton saveButton = null; 105 private JButton deleteButton = null; 106 private final JCheckBox autoRunBox = new JCheckBox(Bundle.getMessage("AutoRun")); 107 private final JCheckBox loadAtStartupBox = new JCheckBox(Bundle.getMessage("LoadAtStartup")); 108 109 private final JRadioButton radioTrainsFromRoster = new JRadioButton(Bundle.getMessage("TrainsFromRoster")); 110 private final JRadioButton radioTrainsFromOps = new JRadioButton(Bundle.getMessage("TrainsFromTrains")); 111 private final JRadioButton radioTrainsFromUser = new JRadioButton(Bundle.getMessage("TrainsFromUser")); 112 private final JRadioButton radioTrainsFromSetLater = new JRadioButton(Bundle.getMessage("TrainsFromSetLater")); 113 private final ButtonGroup trainsFromButtonGroup = new ButtonGroup(); 114 115 private final JRadioButton allocateBySafeRadioButton = new JRadioButton(Bundle.getMessage("ToSafeSections")); 116 private final JRadioButton allocateAllTheWayRadioButton = new JRadioButton(Bundle.getMessage("AsFarAsPos")); 117 private final JRadioButton allocateNumberOfBlocks = new JRadioButton(Bundle.getMessage("NumberOfBlocks") + ":"); 118 private final ButtonGroup allocateMethodButtonGroup = new ButtonGroup(); 119 private final JSpinner allocateCustomSpinner = new JSpinner(new SpinnerNumberModel(3, 1, 100, 1)); 120 private final JCheckBox terminateWhenDoneBox = new JCheckBox(Bundle.getMessage("TerminateWhenDone")); 121 private final JPanel terminateWhenDoneDetails = new JPanel(); 122 private final JComboBox<String> nextTrain = new JComboBox<>(); 123 private final JLabel nextTrainLabel = new JLabel(Bundle.getMessage("TerminateWhenDoneNextTrain")); 124 private final JSpinner prioritySpinner = new JSpinner(new SpinnerNumberModel(5, 0, 100, 1)); 125 private final JCheckBox resetWhenDoneBox = new JCheckBox(Bundle.getMessage("ResetWhenDone")); 126 private final JCheckBox reverseAtEndBox = new JCheckBox(Bundle.getMessage("ReverseAtEnd")); 127 128 int delayedStartInt[] = new int[]{ActiveTrain.NODELAY, ActiveTrain.TIMEDDELAY, ActiveTrain.SENSORDELAY}; 129 String delayedStartString[] = new String[]{Bundle.getMessage("DelayedStartNone"), Bundle.getMessage("DelayedStartTimed"), Bundle.getMessage("DelayedStartSensor")}; 130 131 private final JComboBox<String> reverseDelayedRestartType = new JComboBox<>(delayedStartString); 132 private final JLabel delayReverseReStartLabel = new JLabel(Bundle.getMessage("DelayRestart")); 133 private final JLabel delayReverseReStartSensorLabel = new JLabel(Bundle.getMessage("RestartSensor")); 134 private final JCheckBox delayReverseResetSensorBox = new JCheckBox(Bundle.getMessage("ResetRestartSensor")); 135 private final NamedBeanComboBox<Sensor> delayReverseReStartSensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance()); 136 private final JSpinner delayReverseMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1)); 137 private final JLabel delayReverseMinLabel = new JLabel(Bundle.getMessage("RestartTimed")); 138 139 private final JCheckBox resetStartSensorBox = new JCheckBox(Bundle.getMessage("ResetStartSensor")); 140 private final JComboBox<String> delayedStartBox = new JComboBox<>(delayedStartString); 141 private final JLabel delayedReStartLabel = new JLabel(Bundle.getMessage("DelayRestart")); 142 private final JLabel delayReStartSensorLabel = new JLabel(Bundle.getMessage("RestartSensor")); 143 private final JCheckBox resetRestartSensorBox = new JCheckBox(Bundle.getMessage("ResetRestartSensor")); 144 private final JComboBox<String> delayedReStartBox = new JComboBox<>(delayedStartString); 145 private final NamedBeanComboBox<Sensor> delaySensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance()); 146 private final NamedBeanComboBox<Sensor> delayReStartSensor = new NamedBeanComboBox<>(jmri.InstanceManager.sensorManagerInstance()); 147 148 private final JSpinner departureHrSpinner = new JSpinner(new SpinnerNumberModel(8, 0, 23, 1)); 149 private final JSpinner departureMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 59, 1)); 150 private final JLabel departureTimeLabel = new JLabel(Bundle.getMessage("DepartureTime")); 151 private final JLabel departureSepLabel = new JLabel(":"); 152 153 private final JSpinner delayMinSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1)); 154 private final JLabel delayMinLabel = new JLabel(Bundle.getMessage("RestartTimed")); 155 156 private final JComboBox<String> trainTypeBox = new JComboBox<>(); 157 // Note: See also items related to automatically running trains near the end of this module 158 159 boolean transitsFromSpecificBlock = false; 160 161 /** 162 * Open up a new train window for a given roster entry located in a specific 163 * block. 164 * 165 * @param e the action event triggering the new window 166 * @param re the roster entry to open the new window for 167 * @param b the block where the train is located 168 */ 169 public void initiateTrain(ActionEvent e, RosterEntry re, Block b) { 170 initiateTrain(e); 171 if (_TrainsFrom == TrainsFrom.TRAINSFROMROSTER && re != null) { 172 setRosterComboBox(rosterComboBox, re.getId()); 173 //Add in some bits of code as some point to filter down the transits that can be used. 174 } 175 if (b != null && selectedTransit != null) { 176 List<Transit> transitList = _TransitManager.getListUsingBlock(b); 177 List<Transit> transitEntryList = _TransitManager.getListEntryBlock(b); 178 for (Transit t : transitEntryList) { 179 if (!transitList.contains(t)) { 180 transitList.add(t); 181 } 182 } 183 transitsFromSpecificBlock = true; 184 initializeFreeTransitsCombo(transitList); 185 List<Block> tmpBlkList = new ArrayList<>(); 186 if (selectedTransit.getEntryBlocksList().contains(b)) { 187 tmpBlkList = selectedTransit.getEntryBlocksList(); 188 inTransitBox.setSelected(false); 189 } else if (selectedTransit.containsBlock(b)) { 190 tmpBlkList = selectedTransit.getInternalBlocksList(); 191 inTransitBox.setSelected(true); 192 } 193 List<Integer> tmpSeqList = selectedTransit.getBlockSeqList(); 194 for (int i = 0; i < tmpBlkList.size(); i++) { 195 if (tmpBlkList.get(i) == b) { 196 setComboBox(startingBlockBox, getBlockName(b) + "-" + tmpSeqList.get(i)); 197 break; 198 } 199 } 200 } 201 } 202 203 /** 204 * Displays a window that allows a new ActiveTrain to be activated. 205 * <p> 206 * Called by Dispatcher in response to the dispatcher clicking the New Train 207 * button. 208 * 209 * @param e the action event triggering the window display 210 */ 211 protected void initiateTrain(ActionEvent e) { 212 // set Dispatcher defaults 213 _TrainsFrom = _dispatcher.getTrainsFrom(); 214 _ActiveTrainsList = _dispatcher.getActiveTrainsList(); 215 // create window if needed 216 if (initiateFrame == null) { 217 initiateFrame = this; 218 initiateFrame.setTitle(Bundle.getMessage("AddTrainTitle")); 219 initiateFrame.addHelpMenu("package.jmri.jmrit.dispatcher.NewTrain", true); 220 initiatePane = initiateFrame.getContentPane(); 221 initiatePane.setLayout(new BoxLayout(initiatePane, BoxLayout.Y_AXIS)); 222 223 // add buttons to load and save train information 224 JPanel p0 = new JPanel(); 225 p0.setLayout(new FlowLayout()); 226 p0.add(loadButton = new JButton(Bundle.getMessage("LoadButton"))); 227 loadButton.addActionListener(new ActionListener() { 228 @Override 229 public void actionPerformed(ActionEvent e) { 230 loadTrainInfo(e); 231 } 232 }); 233 loadButton.setToolTipText(Bundle.getMessage("LoadButtonHint")); 234 p0.add(saveButton = new JButton(Bundle.getMessage("SaveButton"))); 235 saveButton.addActionListener(new ActionListener() { 236 @Override 237 public void actionPerformed(ActionEvent e) { 238 saveTrainInfo(e,_TrainsFrom == TrainsFrom.TRAINSFROMSETLATER ? true : false ); 239 } 240 }); 241 saveButton.setToolTipText(Bundle.getMessage("SaveButtonHint")); 242 p0.add(deleteButton = new JButton(Bundle.getMessage("DeleteButton"))); 243 deleteButton.addActionListener(new ActionListener() { 244 @Override 245 public void actionPerformed(ActionEvent e) { 246 deleteTrainInfo(e); 247 } 248 }); 249 deleteButton.setToolTipText(Bundle.getMessage("DeleteButtonHint")); 250 251 // add items relating to both manually run and automatic trains. 252 253 // Trains From choices. 254 JPanel p0a = new JPanel(); 255 p0a.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainsFrom"))); 256 p0a.setLayout(new FlowLayout()); 257 trainsFromButtonGroup.add(radioTrainsFromRoster); 258 trainsFromButtonGroup.add(radioTrainsFromOps); 259 trainsFromButtonGroup.add(radioTrainsFromUser); 260 trainsFromButtonGroup.add(radioTrainsFromSetLater); 261 p0a.add(radioTrainsFromRoster); 262 radioTrainsFromRoster.setToolTipText(Bundle.getMessage("TrainsFromRosterHint")); 263 p0a.add(radioTrainsFromOps); 264 radioTrainsFromOps.setToolTipText(Bundle.getMessage("TrainsFromTrainsHint")); 265 p0a.add(radioTrainsFromUser); 266 radioTrainsFromUser.setToolTipText(Bundle.getMessage("TrainsFromUserHint")); 267 p0a.add(radioTrainsFromSetLater); 268 radioTrainsFromSetLater.setToolTipText(Bundle.getMessage("TrainsFromSetLaterHint")); 269 270 radioTrainsFromOps.addItemListener(new ItemListener() { 271 @Override 272 public void itemStateChanged(ItemEvent e) { 273 if (e.getStateChange() == ItemEvent.SELECTED) { 274 _TrainsFrom = TrainsFrom.TRAINSFROMOPS; 275 setTrainsFromOptions(_TrainsFrom); 276 } 277 } 278 }); 279 280 radioTrainsFromRoster.addItemListener(new ItemListener() { 281 @Override 282 public void itemStateChanged(ItemEvent e) { 283 if (e.getStateChange() == ItemEvent.SELECTED) { 284 _TrainsFrom = TrainsFrom.TRAINSFROMROSTER; 285 setTrainsFromOptions(_TrainsFrom); 286 } 287 } 288 }); 289 radioTrainsFromUser.addItemListener(new ItemListener() { 290 @Override 291 public void itemStateChanged(ItemEvent e) { 292 if (e.getStateChange() == ItemEvent.SELECTED) { 293 _TrainsFrom = TrainsFrom.TRAINSFROMUSER; 294 setTrainsFromOptions(_TrainsFrom); 295 } 296 } 297 }); 298 radioTrainsFromSetLater.addItemListener(new ItemListener() { 299 @Override 300 public void itemStateChanged(ItemEvent e) { 301 if (e.getStateChange() == ItemEvent.SELECTED) { 302 _TrainsFrom = TrainsFrom.TRAINSFROMSETLATER; 303 setTrainsFromOptions(_TrainsFrom); 304 } 305 } 306 }); 307 p0a.add(allocateCustomSpinner); 308 initiatePane.add(p0a); 309 310 JPanel p1 = new JPanel(); 311 p1.setLayout(new FlowLayout()); 312 p1.add(new JLabel(Bundle.getMessage("TransitBoxLabel") + " :")); 313 p1.add(transitSelectBox); 314 transitSelectBox.addActionListener(new ActionListener() { 315 @Override 316 public void actionPerformed(ActionEvent e) { 317 handleTransitSelectionChanged(e); 318 } 319 }); 320 transitSelectBox.setToolTipText(Bundle.getMessage("TransitBoxHint")); 321 p1.add(trainBoxLabel); 322 p1.add(trainSelectBox); 323 trainSelectBox.addActionListener(new ActionListener() { 324 @Override 325 public void actionPerformed(ActionEvent e) { 326 handleTrainSelectionChanged(); 327 } 328 }); 329 trainSelectBox.setToolTipText(Bundle.getMessage("TrainBoxHint")); 330 331 rosterComboBox = new RosterEntryComboBox(); 332 initializeFreeRosterEntriesCombo(); 333 rosterComboBox.addActionListener(new ActionListener() { 334 @Override 335 public void actionPerformed(ActionEvent e) { 336 handleRosterSelectionChanged(e); 337 } 338 }); 339 p1.add(rosterComboBox); 340 341 initiatePane.add(p1); 342 JPanel p1a = new JPanel(); 343 p1a.setLayout(new FlowLayout()); 344 p1a.add(trainFieldLabel); 345 p1a.add(trainNameField); 346 trainNameField.setToolTipText(Bundle.getMessage("TrainFieldHint")); 347 p1a.add(dccAddressFieldLabel); 348 p1a.add(dccAddressSpinner); 349 dccAddressSpinner.setToolTipText(Bundle.getMessage("DccAddressFieldHint")); 350 initiatePane.add(p1a); 351 JPanel p2 = new JPanel(); 352 p2.setLayout(new FlowLayout()); 353 p2.add(inTransitBox); 354 inTransitBox.addActionListener(new ActionListener() { 355 @Override 356 public void actionPerformed(ActionEvent e) { 357 handleInTransitClick(e); 358 } 359 }); 360 inTransitBox.setToolTipText(Bundle.getMessage("InTransitBoxHint")); 361 initiatePane.add(p2); 362 JPanel p3 = new JPanel(); 363 p3.setLayout(new FlowLayout()); 364 p3.add(new JLabel(Bundle.getMessage("StartingBlockBoxLabel") + " :")); 365 p3.add(startingBlockBox); 366 startingBlockBox.setToolTipText(Bundle.getMessage("StartingBlockBoxHint")); 367 startingBlockBox.addActionListener(new ActionListener() { 368 @Override 369 public void actionPerformed(ActionEvent e) { 370 handleStartingBlockSelectionChanged(e); 371 } 372 }); 373 initiatePane.add(p3); 374 JPanel p4 = new JPanel(); 375 p4.setLayout(new FlowLayout()); 376 p4.add(new JLabel(Bundle.getMessage("DestinationBlockBoxLabel") + ":")); 377 p4.add(destinationBlockBox); 378 destinationBlockBox.setToolTipText(Bundle.getMessage("DestinationBlockBoxHint")); 379 JPanel p4a = new JPanel(); 380 initiatePane.add(p4); 381 p4a.add(trainDetectionLabel); 382 initializeTrainDetectionBox(); 383 p4a.add(trainDetectionComboBox); 384 trainDetectionComboBox.setToolTipText(Bundle.getMessage("TrainDetectionBoxHint")); 385 initiatePane.add(p4a); 386 JPanel p4b = new JPanel(); 387 p4b.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("AllocateMethodLabel"))); 388 p4b.setLayout(new FlowLayout()); 389 allocateMethodButtonGroup.add(allocateAllTheWayRadioButton); 390 allocateMethodButtonGroup.add(allocateBySafeRadioButton); 391 allocateMethodButtonGroup.add(allocateNumberOfBlocks); 392 p4b.add(allocateAllTheWayRadioButton); 393 allocateAllTheWayRadioButton.setToolTipText(Bundle.getMessage("AllocateAllTheWayHint")); 394 p4b.add(allocateBySafeRadioButton); 395 allocateBySafeRadioButton.setToolTipText(Bundle.getMessage("AllocateSafeHint")); 396 p4b.add(allocateNumberOfBlocks); 397 allocateNumberOfBlocks.setToolTipText(Bundle.getMessage("AllocateMethodHint")); 398 allocateAllTheWayRadioButton.addActionListener(new ActionListener() { 399 @Override 400 public void actionPerformed(ActionEvent e) { 401 handleAllocateAllTheWayButtonChanged(e); 402 } 403 }); 404 allocateBySafeRadioButton.addActionListener(new ActionListener() { 405 @Override 406 public void actionPerformed(ActionEvent e) { 407 handleAllocateBySafeButtonChanged(e); 408 } 409 }); 410 allocateNumberOfBlocks.addActionListener(new ActionListener() { 411 @Override 412 public void actionPerformed(ActionEvent e) { 413 handleAllocateNumberOfBlocksButtonChanged(e); 414 } 415 }); 416 p4b.add(allocateCustomSpinner); 417 allocateCustomSpinner.setToolTipText(Bundle.getMessage("AllocateMethodHint")); 418 initiatePane.add(p4b); 419 JPanel p6 = new JPanel(); 420 p6.setLayout(new FlowLayout()); 421 p6.add(resetWhenDoneBox); 422 resetWhenDoneBox.addActionListener(new ActionListener() { 423 @Override 424 public void actionPerformed(ActionEvent e) { 425 handleResetWhenDoneClick(e); 426 } 427 }); 428 resetWhenDoneBox.setToolTipText(Bundle.getMessage("ResetWhenDoneBoxHint")); 429 initiatePane.add(p6); 430 JPanel p6a = new JPanel(); 431 p6a.setLayout(new FlowLayout()); 432 ((FlowLayout) p6a.getLayout()).setVgap(1); 433 p6a.add(delayedReStartLabel); 434 p6a.add(delayedReStartBox); 435 p6a.add(resetRestartSensorBox); 436 resetRestartSensorBox.setToolTipText(Bundle.getMessage("ResetRestartSensorHint")); 437 resetRestartSensorBox.setSelected(true); 438 delayedReStartBox.addActionListener(new ActionListener() { 439 @Override 440 public void actionPerformed(ActionEvent e) { 441 handleResetWhenDoneClick(e); 442 } 443 }); 444 delayedReStartBox.setToolTipText(Bundle.getMessage("DelayedReStartHint")); 445 initiatePane.add(p6a); 446 447 JPanel p6b = new JPanel(); 448 p6b.setLayout(new FlowLayout()); 449 ((FlowLayout) p6b.getLayout()).setVgap(1); 450 p6b.add(delayMinLabel); 451 p6b.add(delayMinSpinner); // already set to 0 452 delayMinSpinner.setToolTipText(Bundle.getMessage("RestartTimedHint")); 453 p6b.add(delayReStartSensorLabel); 454 p6b.add(delayReStartSensor); 455 delayReStartSensor.setAllowNull(true); 456 handleResetWhenDoneClick(null); 457 initiatePane.add(p6b); 458 459 initiatePane.add(new JSeparator()); 460 461 JPanel p10 = new JPanel(); 462 p10.setLayout(new FlowLayout()); 463 p10.add(reverseAtEndBox); 464 reverseAtEndBox.setToolTipText(Bundle.getMessage("ReverseAtEndBoxHint")); 465 initiatePane.add(p10); 466 reverseAtEndBox.addActionListener(new ActionListener() { 467 @Override 468 public void actionPerformed(ActionEvent e) { 469 handleReverseAtEndBoxClick(e); 470 } 471 }); 472 JPanel pDelayReverseRestartDetails = new JPanel(); 473 pDelayReverseRestartDetails.setLayout(new FlowLayout()); 474 ((FlowLayout) pDelayReverseRestartDetails.getLayout()).setVgap(1); 475 pDelayReverseRestartDetails.add(delayReverseReStartLabel); 476 pDelayReverseRestartDetails.add(reverseDelayedRestartType); 477 pDelayReverseRestartDetails.add(delayReverseResetSensorBox); 478 delayReverseResetSensorBox.setToolTipText(Bundle.getMessage("ReverseResetRestartSensorHint")); 479 delayReverseResetSensorBox.setSelected(true); 480 reverseDelayedRestartType.addActionListener(new ActionListener() { 481 @Override 482 public void actionPerformed(ActionEvent e) { 483 handleReverseAtEndBoxClick(e); 484 } 485 }); 486 reverseDelayedRestartType.setToolTipText(Bundle.getMessage("ReverseDelayedReStartHint")); 487 initiatePane.add(pDelayReverseRestartDetails); 488 489 JPanel pDelayReverseRestartDetails2 = new JPanel(); 490 pDelayReverseRestartDetails2.setLayout(new FlowLayout()); 491 ((FlowLayout) pDelayReverseRestartDetails2.getLayout()).setVgap(1); 492 pDelayReverseRestartDetails2.add(delayReverseMinLabel); 493 pDelayReverseRestartDetails2.add(delayReverseMinSpinner); // already set to 0 494 delayReverseMinSpinner.setToolTipText(Bundle.getMessage("ReverseRestartTimedHint")); 495 pDelayReverseRestartDetails2.add(delayReverseReStartSensorLabel); 496 pDelayReverseRestartDetails2.add(delayReverseReStartSensor); 497 delayReverseReStartSensor.setAllowNull(true); 498 handleReverseAtEndBoxClick(null); 499 initiatePane.add(pDelayReverseRestartDetails2); 500 501 initiatePane.add(new JSeparator()); 502 503 JPanel p10a = new JPanel(); 504 p10a.setLayout(new FlowLayout()); 505 p10a.add(terminateWhenDoneBox); 506 terminateWhenDoneBox.addActionListener(new ActionListener() { 507 @Override 508 public void actionPerformed(ActionEvent e) { 509 handleTerminateWhenDoneBoxClick(e); 510 } 511 }); 512 initiatePane.add(p10a); 513 terminateWhenDoneDetails.setLayout(new FlowLayout()); 514 terminateWhenDoneDetails.add(nextTrainLabel); 515 terminateWhenDoneDetails.add(nextTrain); 516 nextTrain.setToolTipText(Bundle.getMessage("TerminateWhenDoneNextTrainHint")); 517 initiatePane.add(terminateWhenDoneDetails); 518 handleTerminateWhenDoneBoxClick(null); 519 520 initiatePane.add(new JSeparator()); 521 522 JPanel p8 = new JPanel(); 523 p8.setLayout(new FlowLayout()); 524 p8.add(new JLabel(Bundle.getMessage("PriorityLabel") + ":")); 525 p8.add(prioritySpinner); // already set to 5 526 prioritySpinner.setToolTipText(Bundle.getMessage("PriorityHint")); 527 p8.add(new JLabel(" ")); 528 p8.add(new JLabel(Bundle.getMessage("TrainTypeBoxLabel"))); 529 initializeTrainTypeBox(); 530 p8.add(trainTypeBox); 531 trainTypeBox.setSelectedIndex(1); 532 trainTypeBox.setToolTipText(Bundle.getMessage("TrainTypeBoxHint")); 533 initiatePane.add(p8); 534 JPanel p9 = new JPanel(); 535 p9.setLayout(new FlowLayout()); 536 p9.add(new JLabel(Bundle.getMessage("DelayedStart"))); 537 p9.add(delayedStartBox); 538 delayedStartBox.setToolTipText(Bundle.getMessage("DelayedStartHint")); 539 delayedStartBox.addActionListener(new ActionListener() { 540 @Override 541 public void actionPerformed(ActionEvent e) { 542 handleDelayStartClick(e); 543 } 544 }); 545 p9.add(departureTimeLabel); 546 departureHrSpinner.setEditor(new JSpinner.NumberEditor(departureHrSpinner, "00")); 547 p9.add(departureHrSpinner); 548 departureHrSpinner.setValue(8); 549 departureHrSpinner.setToolTipText(Bundle.getMessage("DepartureTimeHrHint")); 550 p9.add(departureSepLabel); 551 departureMinSpinner.setEditor(new JSpinner.NumberEditor(departureMinSpinner, "00")); 552 p9.add(departureMinSpinner); 553 departureMinSpinner.setValue(0); 554 departureMinSpinner.setToolTipText(Bundle.getMessage("DepartureTimeMinHint")); 555 p9.add(delaySensor); 556 delaySensor.setAllowNull(true); 557 p9.add(resetStartSensorBox); 558 resetStartSensorBox.setToolTipText(Bundle.getMessage("ResetStartSensorHint")); 559 resetStartSensorBox.setSelected(true); 560 handleDelayStartClick(null); 561 initiatePane.add(p9); 562 563 JPanel p11 = new JPanel(); 564 p11.setLayout(new FlowLayout()); 565 p11.add(loadAtStartupBox); 566 loadAtStartupBox.setToolTipText(Bundle.getMessage("LoadAtStartupBoxHint")); 567 loadAtStartupBox.setSelected(false); 568 initiatePane.add(p11); 569 570 initiatePane.add(new JSeparator()); 571 JPanel p5 = new JPanel(); 572 p5.setLayout(new FlowLayout()); 573 p5.add(autoRunBox); 574 autoRunBox.addActionListener(new ActionListener() { 575 @Override 576 public void actionPerformed(ActionEvent e) { 577 handleAutoRunClick(e); 578 } 579 }); 580 autoRunBox.setToolTipText(Bundle.getMessage("AutoRunBoxHint")); 581 autoRunBox.setSelected(false); 582 initiatePane.add(p5); 583 584 initializeAutoRunItems(); 585 586 JPanel p7 = new JPanel(); 587 p7.setLayout(new FlowLayout()); 588 JButton cancelButton = null; 589 p7.add(cancelButton = new JButton(Bundle.getMessage("ButtonCancel"))); 590 cancelButton.addActionListener(new ActionListener() { 591 @Override 592 public void actionPerformed(ActionEvent e) { 593 cancelInitiateTrain(e); 594 } 595 }); 596 cancelButton.setToolTipText(Bundle.getMessage("CancelButtonHint")); 597 p7.add(addNewTrainButton = new JButton(Bundle.getMessage("ButtonCreate"))); 598 addNewTrainButton.addActionListener(new ActionListener() { 599 @Override 600 public void actionPerformed(ActionEvent e) { 601 addNewTrain(e); 602 } 603 }); 604 addNewTrainButton.setToolTipText(Bundle.getMessage("AddNewTrainButtonHint")); 605 606 JPanel mainPane = new JPanel(); 607 mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS)); 608 JScrollPane scrPane = new JScrollPane(initiatePane); 609 mainPane.add(p0); 610 mainPane.add(scrPane); 611 mainPane.add(p7); 612 initiateFrame.setContentPane(mainPane); 613 switch (_TrainsFrom) { 614 case TRAINSFROMROSTER: 615 radioTrainsFromRoster.setSelected(true); 616 break; 617 case TRAINSFROMOPS: 618 radioTrainsFromOps.setSelected(true); 619 break; 620 case TRAINSFROMUSER: 621 radioTrainsFromUser.setSelected(true); 622 break; 623 case TRAINSFROMSETLATER: 624 default: 625 radioTrainsFromSetLater.setSelected(true); 626 } 627 628 } 629 setAutoRunDefaults(); 630 autoRunBox.setSelected(false); 631 loadAtStartupBox.setSelected(false); 632 initializeFreeTransitsCombo(new ArrayList<Transit>()); 633 nextTrain.addItem(""); 634 refreshNextTrainCombo(); 635 setTrainsFromOptions(_TrainsFrom); 636 initiateFrame.pack(); 637 initiateFrame.setVisible(true); 638 } 639 640 private void refreshNextTrainCombo() { 641 Object saveEntry = null; 642 if (nextTrain.getSelectedIndex() > 0) { 643 saveEntry=nextTrain.getSelectedItem(); 644 } 645 nextTrain.removeAll(); 646 for (String file: _tiFile.getTrainInfoFileNames()) { 647 nextTrain.addItem(file); 648 } 649 if (saveEntry != null) { 650 nextTrain.setSelectedItem(saveEntry); 651 } 652 } 653 private void setTrainsFromOptions(TrainsFrom transFrom) { 654 switch (transFrom) { 655 case TRAINSFROMROSTER: 656 initializeFreeRosterEntriesCombo(); 657 trainBoxLabel.setVisible(true); 658 rosterComboBox.setVisible(true); 659 trainSelectBox.setVisible(false); 660 trainFieldLabel.setVisible(false); 661 trainNameField.setVisible(false); 662 dccAddressFieldLabel.setVisible(false); 663 dccAddressSpinner.setVisible(false); 664 break; 665 case TRAINSFROMOPS: 666 initializeFreeTrainsCombo(); 667 trainBoxLabel.setVisible(true); 668 trainSelectBox.setVisible(true); 669 rosterComboBox.setVisible(false); 670 trainFieldLabel.setVisible(false); 671 trainNameField.setVisible(false); 672 dccAddressFieldLabel.setVisible(true); 673 dccAddressSpinner.setVisible(true); 674 setSpeedProfileOptions(false); 675 break; 676 case TRAINSFROMUSER: 677 trainNameField.setText(""); 678 trainBoxLabel.setVisible(false); 679 trainSelectBox.setVisible(false); 680 rosterComboBox.setVisible(false); 681 trainFieldLabel.setVisible(true); 682 trainNameField.setVisible(true); 683 dccAddressFieldLabel.setVisible(true); 684 dccAddressSpinner.setVisible(true); 685 dccAddressSpinner.setEnabled(true); 686 setSpeedProfileOptions(false); 687 break; 688 case TRAINSFROMSETLATER: 689 default: 690 trainBoxLabel.setVisible(false); 691 rosterComboBox.setVisible(false); 692 trainSelectBox.setVisible(false); 693 trainFieldLabel.setVisible(false); 694 trainNameField.setVisible(false); 695 dccAddressFieldLabel.setVisible(false); 696 dccAddressSpinner.setVisible(false); 697 } 698 } 699 700 private void initializeTrainTypeBox() { 701 trainTypeBox.removeAllItems(); 702 trainTypeBox.addItem("<" + Bundle.getMessage("None").toLowerCase() + ">"); // <none> 703 trainTypeBox.addItem(Bundle.getMessage("LOCAL_PASSENGER")); 704 trainTypeBox.addItem(Bundle.getMessage("LOCAL_FREIGHT")); 705 trainTypeBox.addItem(Bundle.getMessage("THROUGH_PASSENGER")); 706 trainTypeBox.addItem(Bundle.getMessage("THROUGH_FREIGHT")); 707 trainTypeBox.addItem(Bundle.getMessage("EXPRESS_PASSENGER")); 708 trainTypeBox.addItem(Bundle.getMessage("EXPRESS_FREIGHT")); 709 trainTypeBox.addItem(Bundle.getMessage("MOW")); 710 // NOTE: The above must correspond in order and name to definitions in ActiveTrain.java. 711 } 712 713 private void initializeTrainDetectionBox() { 714 trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionWholeTrain"),TrainDetection.TRAINDETECTION_WHOLETRAIN)); 715 trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionHeadAndTail"),TrainDetection.TRAINDETECTION_HEADANDTAIL)); 716 trainDetectionComboBox.addItem(new TrainDetectionItem(Bundle.getMessage("TrainDetectionHeadOnly"),TrainDetection.TRAINDETECTION_HEADONLY)); 717 } 718 719 private void handleTransitSelectionChanged(ActionEvent e) { 720 int index = transitSelectBox.getSelectedIndex(); 721 if (index < 0) { 722 return; 723 } 724 Transit t = transitSelectBox.getSelectedItem(); 725 if ((t != null) && (t != selectedTransit)) { 726 selectedTransit = t; 727 initializeStartingBlockCombo(); 728 initializeDestinationBlockCombo(); 729 initiateFrame.pack(); 730 } 731 } 732 733 private void handleInTransitClick(ActionEvent e) { 734 if (!inTransitBox.isSelected() && selectedTransit.getEntryBlocksList().isEmpty()) { 735 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle 736 .getMessage("NoEntryBlocks"), Bundle.getMessage("MessageTitle"), 737 JmriJOptionPane.INFORMATION_MESSAGE); 738 inTransitBox.setSelected(true); 739 } 740 initializeStartingBlockCombo(); 741 initializeDestinationBlockCombo(); 742 initiateFrame.pack(); 743 } 744 745 // private void handleTrainSelectionChanged(ActionEvent e) { 746 private void handleTrainSelectionChanged() { 747 if (_TrainsFrom != TrainsFrom.TRAINSFROMOPS) { 748 return; 749 } 750 int ix = trainSelectBox.getSelectedIndex(); 751 if (ix < 1) { // no train selected 752 dccAddressSpinner.setEnabled(false); 753 return; 754 } 755 dccAddressSpinner.setEnabled(true); 756 int dccAddress; 757 try { 758 dccAddress = Integer.parseInt((((Train) trainSelectBox.getSelectedItem()).getLeadEngineDccAddress())); 759 } catch (NumberFormatException Ex) { 760 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error43"), 761 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 762 return; 763 } 764 dccAddressSpinner.setValue (dccAddress); 765 } 766 767 private void handleRosterSelectionChanged(ActionEvent e) { 768 if (_TrainsFrom != TrainsFrom.TRAINSFROMROSTER) { 769 return; 770 } 771 int ix = rosterComboBox.getSelectedIndex(); 772 if (ix > 0) { // first item is "Select Loco" string 773 RosterEntry r = (RosterEntry) rosterComboBox.getItemAt(ix); 774 // check to see if speed profile exists and is not empty 775 if (r.getSpeedProfile() == null || r.getSpeedProfile().getProfileSize() < 1) { 776 // disable profile boxes etc. 777 setSpeedProfileOptions(false); 778 } else { 779 // enable profile boxes 780 setSpeedProfileOptions(true); 781 } 782 if (r.getAttribute("DispatcherTrainType") != null && !r.getAttribute("DispatcherTrainType").equals("")) { 783 trainTypeBox.setSelectedItem(r.getAttribute("DispatcherTrainType")); 784 } 785 } else { 786 setSpeedProfileOptions(false); 787 } 788 } 789 790 private boolean checkResetWhenDone() { 791 if ((!reverseAtEndBox.isSelected()) && resetWhenDoneBox.isSelected() 792 && (!selectedTransit.canBeResetWhenDone())) { 793 resetWhenDoneBox.setSelected(false); 794 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle 795 .getMessage("NoResetMessage"), Bundle.getMessage("MessageTitle"), 796 JmriJOptionPane.INFORMATION_MESSAGE); 797 return false; 798 } 799 return true; 800 } 801 802 private void handleDelayStartClick(ActionEvent e) { 803 departureHrSpinner.setVisible(false); 804 departureMinSpinner.setVisible(false); 805 departureTimeLabel.setVisible(false); 806 departureSepLabel.setVisible(false); 807 delaySensor.setVisible(false); 808 resetStartSensorBox.setVisible(false); 809 if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 810 departureHrSpinner.setVisible(true); 811 departureMinSpinner.setVisible(true); 812 departureTimeLabel.setVisible(true); 813 departureSepLabel.setVisible(true); 814 } else if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 815 delaySensor.setVisible(true); 816 resetStartSensorBox.setVisible(true); 817 } 818 initiateFrame.pack(); // to fit extra hh:mm in window 819 } 820 821 private void handleResetWhenDoneClick(ActionEvent e) { 822 delayMinSpinner.setVisible(false); 823 delayMinLabel.setVisible(false); 824 delayedReStartLabel.setVisible(false); 825 delayedReStartBox.setVisible(false); 826 delayReStartSensorLabel.setVisible(false); 827 delayReStartSensor.setVisible(false); 828 resetRestartSensorBox.setVisible(false); 829 if (resetWhenDoneBox.isSelected()) { 830 delayedReStartLabel.setVisible(true); 831 delayedReStartBox.setVisible(true); 832 terminateWhenDoneBox.setSelected(false); 833 if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 834 delayMinSpinner.setVisible(true); 835 delayMinLabel.setVisible(true); 836 } else if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 837 delayReStartSensor.setVisible(true); 838 delayReStartSensorLabel.setVisible(true); 839 resetRestartSensorBox.setVisible(true); 840 } 841 } else { 842 terminateWhenDoneBox.setEnabled(true); 843 } 844 initiateFrame.pack(); 845 } 846 847 private void handleTerminateWhenDoneBoxClick(ActionEvent e) { 848 if (terminateWhenDoneBox.isSelected()) { 849 refreshNextTrainCombo(); 850 resetWhenDoneBox.setSelected(false); 851 terminateWhenDoneDetails.setVisible(true); 852 } else { 853 terminateWhenDoneDetails.setVisible(false); 854 // leave it 855 //nextTrain.setSelectedItem(""); 856 } 857 } 858 private void handleReverseAtEndBoxClick(ActionEvent e) { 859 delayReverseMinSpinner.setVisible(false); 860 delayReverseMinLabel.setVisible(false); 861 delayReverseReStartLabel.setVisible(false); 862 reverseDelayedRestartType.setVisible(false); 863 delayReverseReStartSensorLabel.setVisible(false); 864 delayReverseReStartSensor.setVisible(false); 865 delayReverseResetSensorBox.setVisible(false); 866 if (reverseAtEndBox.isSelected()) { 867 delayReverseReStartLabel.setVisible(true); 868 reverseDelayedRestartType.setVisible(true); 869 if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 870 delayReverseMinSpinner.setVisible(true); 871 delayReverseMinLabel.setVisible(true); 872 } else if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 873 delayReverseReStartSensor.setVisible(true); 874 delayReStartSensorLabel.setVisible(true); 875 delayReverseResetSensorBox.setVisible(true); 876 } 877 } 878 initiateFrame.pack(); 879 880 if (resetWhenDoneBox.isSelected()) { 881 terminateWhenDoneBox.setSelected(false); 882 terminateWhenDoneBox.setEnabled(false); 883 } else { 884 terminateWhenDoneBox.setEnabled(true); 885 } 886 } 887 888 private void handleAutoRunClick(ActionEvent e) { 889 if (autoRunBox.isSelected()) { 890 showAutoRunItems(); 891 } else { 892 hideAutoRunItems(); 893 } 894 initiateFrame.pack(); 895 } 896 897 private void handleStartingBlockSelectionChanged(ActionEvent e) { 898 initializeDestinationBlockCombo(); 899 initiateFrame.pack(); 900 } 901 902 private void handleAllocateAllTheWayButtonChanged(ActionEvent e) { 903 allocateCustomSpinner.setVisible(false); 904 } 905 906 private void handleAllocateBySafeButtonChanged(ActionEvent e) { 907 allocateCustomSpinner.setVisible(false); 908 } 909 910 private void handleAllocateNumberOfBlocksButtonChanged(ActionEvent e) { 911 allocateCustomSpinner.setVisible(true); 912 } 913 914 private void cancelInitiateTrain(ActionEvent e) { 915 _dispatcher.newTrainDone(null); 916 } 917 918 /** 919 * Handles press of "Add New Train" button by edit-checking populated values 920 * then (if no errors) creating an ActiveTrain and (optionally) an 921 * AutoActiveTrain 922 */ 923 private void addNewTrain(ActionEvent e) { 924 // get information 925 if (selectedTransit == null) { 926 // no transits available 927 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error15"), 928 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 929 cancelInitiateTrain(null); 930 return; 931 } 932 String transitName = selectedTransit.getDisplayName(); 933 String trainName = ""; 934 int index = startingBlockBox.getSelectedIndex(); 935 if (index < 0) { 936 return; 937 } 938 String startBlockName = startingBlockBoxList.get(index).getDisplayName(); 939 int startBlockSeq = startingBlockSeqList.get(index).intValue(); 940 index = destinationBlockBox.getSelectedIndex(); 941 if (index < 0) { 942 return; 943 } 944 String endBlockName = destinationBlockBoxList.get(index).getDisplayName(); 945 int endBlockSeq = destinationBlockSeqList.get(index).intValue(); 946 boolean autoRun = autoRunBox.isSelected(); 947 if (!checkResetWhenDone()) { 948 return; 949 } 950 boolean resetWhenDone = resetWhenDoneBox.isSelected(); 951 boolean reverseAtEnd = reverseAtEndBox.isSelected(); 952 index = trainDetectionComboBox.getSelectedIndex(); 953 if (index < 0) { 954 return; 955 } 956 TrainDetection trainDetection = ((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value; 957 int allocateMethod = 3; 958 if (allocateAllTheWayRadioButton.isSelected()) { 959 allocateMethod = ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN; 960 } else if (allocateBySafeRadioButton.isSelected()) { 961 allocateMethod = ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS; 962 } else { 963 allocateMethod = (Integer) allocateCustomSpinner.getValue(); 964 } 965 int delayedStart = delayModeFromBox(delayedStartBox); 966 int delayedReStart = delayModeFromBox(delayedReStartBox); 967 int delayedReverseReStart = delayModeFromBox(reverseDelayedRestartType); 968 int departureTimeHours = 8; 969 departureTimeHours = (Integer) departureHrSpinner.getValue(); 970 int departureTimeMinutes = 8; 971 departureTimeMinutes = (Integer) departureMinSpinner.getValue(); 972 int delayRestartMinutes = 0; 973 delayRestartMinutes = (Integer) delayMinSpinner.getValue(); 974 if ((delayRestartMinutes < 0)) { 975 JmriJOptionPane.showMessageDialog(initiateFrame, delayMinSpinner.getValue(), 976 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 977 log.warn("Range error in Delay Restart Time Minutes field"); 978 return; 979 } 980 int delayReverseRestartMinutes = 0; 981 delayReverseRestartMinutes = (Integer) delayReverseMinSpinner.getValue(); 982 if ((delayReverseRestartMinutes < 0)) { 983 JmriJOptionPane.showMessageDialog(initiateFrame, delayReverseMinSpinner.getValue(), 984 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 985 log.warn("Range error in Reverse Delay Restart Time Minutes field"); 986 return; 987 } 988 int tSource = 0; 989 String dccAddress = "unknown"; 990 switch (_TrainsFrom) { 991 case TRAINSFROMROSTER: 992 index = rosterComboBox.getSelectedIndex(); 993 if (index < 1) { // first item is the "Select Loco" message 994 // no train selected 995 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error41"), 996 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 997 return; 998 } 999 RosterEntry r = (RosterEntry) rosterComboBox.getSelectedItem(); 1000 dccAddress = r.getDccAddress(); 1001 trainName = r.titleString(); 1002 if (!isAddressFree(r.getDccLocoAddress().getNumber())) { 1003 // DCC address is already in use by an Active Train 1004 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1005 "Error40", dccAddress), Bundle.getMessage("ErrorTitle"), 1006 JmriJOptionPane.ERROR_MESSAGE); 1007 return; 1008 } 1009 1010 tSource = ActiveTrain.ROSTER; 1011 1012 if (trainTypeBox.getSelectedIndex() != 0 && 1013 (r.getAttribute("DispatcherTrainType") == null || 1014 !r.getAttribute("DispatcherTrainType").equals("" + trainTypeBox.getSelectedItem()))) { 1015 r.putAttribute("DispatcherTrainType", "" + trainTypeBox.getSelectedItem()); 1016 r.updateFile(); 1017 Roster.getDefault().writeRoster(); 1018 } 1019 break; 1020 case TRAINSFROMOPS: 1021 tSource = ActiveTrain.OPERATIONS; 1022 index = trainSelectBox.getSelectedIndex(); 1023 if (index < 1) { // first item is Select Train 1024 // Train not selected 1025 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error42"), 1026 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1027 return; 1028 } 1029 trainName = trainSelectBox.getSelectedItem().toString(); 1030 dccAddress = getDCCAddressFromSpinner(); 1031 if (dccAddress == null) { 1032 return; 1033 } 1034 break; 1035 case TRAINSFROMUSER: 1036 trainName = trainNameField.getText(); 1037 if ((trainName == null) || trainName.equals("")) { 1038 // no train name entered 1039 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error14"), 1040 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1041 return; 1042 } 1043 if (!isTrainFree(trainName)) { 1044 // train name is already in use by an Active Train 1045 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1046 "Error24", trainName), Bundle.getMessage("ErrorTitle"), 1047 JmriJOptionPane.ERROR_MESSAGE); 1048 return; 1049 } 1050 dccAddress = getDCCAddressFromSpinner(); 1051 if (dccAddress == null) { 1052 return; 1053 } 1054 tSource = ActiveTrain.USER; 1055 break; 1056 case TRAINSFROMSETLATER: 1057 default: 1058 trainName = ""; 1059 } 1060 int priority = 5; 1061 priority = (Integer) prioritySpinner.getValue(); 1062 int trainType = trainTypeBox.getSelectedIndex(); 1063 if (autoRunBox.isSelected()) { 1064 if (!readAutoRunItems()) { 1065 return; 1066 } 1067 } 1068 1069 // create a new Active Train 1070 ActiveTrain at = _dispatcher.createActiveTrain(transitName, trainName, tSource, startBlockName, 1071 startBlockSeq, endBlockName, endBlockSeq, autoRun, dccAddress, priority, 1072 resetWhenDone, reverseAtEnd, true, initiateFrame, allocateMethod); 1073 if (at == null) { 1074 return; // error message sent by createActiveTrain 1075 } 1076 if (tSource == ActiveTrain.ROSTER) { 1077 at.setRosterEntry((RosterEntry)rosterComboBox.getSelectedItem()); 1078 } 1079 at.setTrainDetection(trainDetection); 1080 at.setAllocateMethod(allocateMethod); 1081 at.setDelayedStart(delayedStart); 1082 at.setDelayedRestart(delayedReStart); 1083 at.setDepartureTimeHr(departureTimeHours); 1084 at.setDepartureTimeMin(departureTimeMinutes); 1085 at.setRestartDelay(delayRestartMinutes); 1086 at.setDelaySensor(delaySensor.getSelectedItem()); 1087 at.setReverseDelayRestart(delayedReverseReStart); 1088 at.setReverseRestartDelay(delayReverseRestartMinutes); 1089 at.setReverseDelaySensor(delayReverseReStartSensor.getSelectedItem()); 1090 at.setReverseResetRestartSensor(delayReverseResetSensorBox.isSelected()); 1091 if ((_dispatcher.isFastClockTimeGE(departureTimeHours, departureTimeMinutes) && delayedStart != ActiveTrain.SENSORDELAY) 1092 || delayedStart == ActiveTrain.NODELAY) { 1093 at.setStarted(); 1094 } 1095 at.setRestartSensor(delayReStartSensor.getSelectedItem()); 1096 at.setResetRestartSensor(resetRestartSensorBox.isSelected()); 1097 at.setTrainType(trainType); 1098 at.setTerminateWhenDone(terminateWhenDoneBox.isSelected()); 1099 at.setNextTrain(_nextTrain); 1100 if (autoRunBox.isSelected()) { 1101 AutoActiveTrain aat = new AutoActiveTrain(at); 1102 setAutoRunItems(aat); 1103 _dispatcher.getAutoTrainsFrame().addAutoActiveTrain(aat); 1104 if (!aat.initialize()) { 1105 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1106 "Error27", at.getTrainName()), Bundle.getMessage("MessageTitle"), 1107 JmriJOptionPane.INFORMATION_MESSAGE); 1108 } 1109 } 1110 _dispatcher.allocateNewActiveTrain(at); 1111 _dispatcher.newTrainDone(at); 1112 } 1113 1114 private String getDCCAddressFromSpinner() { 1115 int address = (Integer) dccAddressSpinner.getValue(); // SpinnerNumberModel 1116 // limits 1117 // address to 1118 // 1 - 9999 1119 // inclusive 1120 if (!isAddressFree(address)) { 1121 // DCC address is already in use by an Active Train 1122 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1123 "Error40", address), Bundle.getMessage("ErrorTitle"), 1124 JmriJOptionPane.ERROR_MESSAGE); 1125 return null; 1126 } 1127 return String.valueOf(address); 1128 } 1129 1130 private void initializeFreeTransitsCombo(List<Transit> transitList) { 1131 Set<Transit> excludeTransits = new HashSet<>(); 1132 for (Transit t : _TransitManager.getNamedBeanSet()) { 1133 if (t.getState() != Transit.IDLE) { 1134 excludeTransits.add(t); 1135 } 1136 } 1137 transitSelectBox.setExcludedItems(excludeTransits); 1138 JComboBoxUtil.setupComboBoxMaxRows(transitSelectBox); 1139 1140 if (transitSelectBox.getItemCount() > 0) { 1141 transitSelectBox.setSelectedIndex(0); 1142 selectedTransit = transitSelectBox.getItemAt(0); 1143 } else { 1144 selectedTransit = null; 1145 } 1146 } 1147 1148 private void initializeFreeRosterEntriesCombo() { 1149 rosterComboBox.update(); 1150 // remove used entries 1151 for (int ix = rosterComboBox.getItemCount() - 1; ix > 1; ix--) { // remove from back first item is the "select loco" message 1152 if ( !isAddressFree( ((RosterEntry)rosterComboBox.getItemAt(ix)).getDccLocoAddress().getNumber() ) ) { 1153 rosterComboBox.removeItemAt(ix); 1154 } 1155 } 1156 } 1157 1158 private void initializeFreeTrainsCombo() { 1159 ActionListener[] als = trainSelectBox.getActionListeners(); 1160 for ( ActionListener al: als) { 1161 trainSelectBox.removeActionListener(al); 1162 } 1163 trainSelectBox.removeAllItems(); 1164 trainSelectBox.addItem("Select Train"); 1165 // initialize free trains from operations 1166 List<Train> trains = jmri.InstanceManager.getDefault(TrainManager.class).getTrainsByNameList(); 1167 if (trains.size() > 0) { 1168 for (int i = 0; i < trains.size(); i++) { 1169 Train t = trains.get(i); 1170 if (t != null) { 1171 String tName = t.getName(); 1172 if (isTrainFree(tName)) { 1173 trainSelectBox.addItem(t); 1174 } 1175 } 1176 } 1177 } 1178 for ( ActionListener al: als) { 1179 trainSelectBox.addActionListener(al); 1180 } 1181 } 1182 1183 /** 1184 * Sets the labels and inputs for speed profile running 1185 * @param b True if the roster entry has valid speed profile else false 1186 */ 1187 private void setSpeedProfileOptions(boolean b) { 1188 useSpeedProfileLabel.setEnabled(b); 1189 useSpeedProfileCheckBox.setEnabled(b); 1190 stopBySpeedProfileLabel.setEnabled(b); 1191 stopBySpeedProfileCheckBox.setEnabled(b); 1192 stopBySpeedProfileAdjustLabel.setEnabled(b); 1193 stopBySpeedProfileAdjustSpinner.setEnabled(b); 1194 if (!b) { 1195 useSpeedProfileCheckBox.setSelected(false); 1196 stopBySpeedProfileCheckBox.setSelected(false); 1197 _useSpeedProfile = false; 1198 _stopBySpeedProfile = false; 1199 } 1200 } 1201 1202 private boolean isTrainFree(String rName) { 1203 for (int j = 0; j < _ActiveTrainsList.size(); j++) { 1204 ActiveTrain at = _ActiveTrainsList.get(j); 1205 if (rName.equals(at.getTrainName())) { 1206 return false; 1207 } 1208 } 1209 return true; 1210 } 1211 1212 private boolean isAddressFree(int addr) { 1213 for (int j = 0; j < _ActiveTrainsList.size(); j++) { 1214 ActiveTrain at = _ActiveTrainsList.get(j); 1215 if (addr == Integer.parseInt(at.getDccAddress())) { 1216 return false; 1217 } 1218 } 1219 return true; 1220 } 1221 1222 private void initializeStartingBlockCombo() { 1223 startingBlockBox.removeAllItems(); 1224 startingBlockBoxList.clear(); 1225 if (!inTransitBox.isSelected() && selectedTransit.getEntryBlocksList().isEmpty()) { 1226 inTransitBox.setSelected(true); 1227 } 1228 if (inTransitBox.isSelected()) { 1229 startingBlockBoxList = selectedTransit.getInternalBlocksList(); 1230 } else { 1231 startingBlockBoxList = selectedTransit.getEntryBlocksList(); 1232 } 1233 startingBlockSeqList = selectedTransit.getBlockSeqList(); 1234 boolean found = false; 1235 for (int i = 0; i < startingBlockBoxList.size(); i++) { 1236 Block b = startingBlockBoxList.get(i); 1237 int seq = startingBlockSeqList.get(i).intValue(); 1238 startingBlockBox.addItem(getBlockName(b) + "-" + seq); 1239 if (!found && b.getState() == Block.OCCUPIED) { 1240 startingBlockBox.setSelectedItem(getBlockName(b) + "-" + seq); 1241 found = true; 1242 } 1243 } 1244 JComboBoxUtil.setupComboBoxMaxRows(startingBlockBox); 1245 } 1246 1247 private void initializeDestinationBlockCombo() { 1248 destinationBlockBox.removeAllItems(); 1249 destinationBlockBoxList.clear(); 1250 int index = startingBlockBox.getSelectedIndex(); 1251 if (index < 0) { 1252 return; 1253 } 1254 Block startBlock = startingBlockBoxList.get(index); 1255 destinationBlockBoxList = selectedTransit.getDestinationBlocksList( 1256 startBlock, inTransitBox.isSelected()); 1257 destinationBlockSeqList = selectedTransit.getDestBlocksSeqList(); 1258 for (int i = 0; i < destinationBlockBoxList.size(); i++) { 1259 Block b = destinationBlockBoxList.get(i); 1260 String bName = getBlockName(b); 1261 if (selectedTransit.getBlockCount(b) > 1) { 1262 int seq = destinationBlockSeqList.get(i).intValue(); 1263 bName = bName + "-" + seq; 1264 } 1265 destinationBlockBox.addItem(bName); 1266 } 1267 JComboBoxUtil.setupComboBoxMaxRows(destinationBlockBox); 1268 } 1269 1270 private String getBlockName(Block b) { 1271 if (b != null) { 1272 return b.getDisplayName(); 1273 } 1274 return " "; 1275 } 1276 1277 protected void showActivateFrame() { 1278 if (initiateFrame != null) { 1279 initializeFreeTransitsCombo(new ArrayList<Transit>()); 1280 initiateFrame.setVisible(true); 1281 } else { 1282 _dispatcher.newTrainDone(null); 1283 } 1284 } 1285 1286 public void showActivateFrame(RosterEntry re) { 1287 showActivateFrame(); 1288 } 1289 1290 private void loadTrainInfo(ActionEvent e) { 1291 String[] names = _tiFile.getTrainInfoFileNames(); 1292 TrainInfo info = null; 1293 if (names.length > 0) { 1294 //prompt user to select a single train info filename from directory list 1295 Object selName = JmriJOptionPane.showInputDialog(initiateFrame, 1296 Bundle.getMessage("LoadTrainChoice"), Bundle.getMessage("LoadTrainTitle"), 1297 JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]); 1298 if ((selName == null) || (((String) selName).equals(""))) { 1299 return; 1300 } 1301 //read xml data from selected filename and move it into the new train dialog box 1302 _trainInfoName = (String) selName; 1303 try { 1304 info = _tiFile.readTrainInfo((String) selName); 1305 if (info != null) { 1306 // process the information just read 1307 trainInfoToDialog(info); 1308 } 1309 } catch (java.io.IOException ioe) { 1310 log.error("IO Exception when reading train info file", ioe); 1311 } catch (org.jdom2.JDOMException jde) { 1312 log.error("JDOM Exception when reading train info file", jde); 1313 } 1314 } 1315 handleDelayStartClick(null); 1316 handleReverseAtEndBoxClick(null); 1317 } 1318 1319 private void saveTrainInfo(ActionEvent e, boolean locoOptional) { 1320 TrainInfo info = null; 1321 try { 1322 info = dialogToTrainInfo(locoOptional); 1323 } catch (IllegalArgumentException ide) { 1324 JmriJOptionPane.showMessageDialog(initiateFrame, ide.getMessage(), 1325 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1326 return; 1327 } 1328 // get file name 1329 String eName = ""; 1330 eName = JmriJOptionPane.showInputDialog(initiateFrame, 1331 Bundle.getMessage("EnterFileName") + " :", _trainInfoName); 1332 if (eName == null) { //Cancel pressed 1333 return; 1334 } 1335 if (eName.length() < 1) { 1336 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error25"), 1337 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1338 return; 1339 } 1340 String fileName = normalizeXmlFileName(eName); 1341 _trainInfoName = fileName; 1342 // check if train info file name is in use 1343 String[] names = _tiFile.getTrainInfoFileNames(); 1344 if (names.length > 0) { 1345 boolean found = false; 1346 for (int i = 0; i < names.length; i++) { 1347 if (fileName.equals(names[i])) { 1348 found = true; 1349 } 1350 } 1351 if (found) { 1352 // file by that name is already present 1353 int selectedValue = JmriJOptionPane.showOptionDialog(initiateFrame, 1354 Bundle.getMessage("Question3", fileName), 1355 Bundle.getMessage("WarningTitle"), JmriJOptionPane.DEFAULT_OPTION, 1356 JmriJOptionPane.QUESTION_MESSAGE, null, 1357 new Object[]{Bundle.getMessage("ButtonReplace"),Bundle.getMessage("ButtonNo")}, 1358 Bundle.getMessage("ButtonNo")); 1359 if (selectedValue != 0 ) { // array position 0 , replace not selected 1360 return; // return without writing if "No" response 1361 } 1362 } 1363 } 1364 // write the Train Info file 1365 try { 1366 _tiFile.writeTrainInfo(info, fileName); 1367 } //catch (org.jdom2.JDOMException jde) { 1368 // log.error("JDOM exception writing Train Info: "+jde); 1369 //} 1370 catch (java.io.IOException ioe) { 1371 log.error("IO exception writing Train Info", ioe); 1372 } 1373 } 1374 1375 private void deleteTrainInfo(ActionEvent e) { 1376 String[] names = _tiFile.getTrainInfoFileNames(); 1377 if (names.length > 0) { 1378 Object selName = JmriJOptionPane.showInputDialog(initiateFrame, 1379 Bundle.getMessage("DeleteTrainChoice"), Bundle.getMessage("DeleteTrainTitle"), 1380 JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]); 1381 if ((selName == null) || (((String) selName).equals(""))) { 1382 return; 1383 } 1384 _tiFile.deleteTrainInfoFile((String) selName); 1385 } 1386 } 1387 1388 private void trainInfoToDialog(TrainInfo info) { 1389 try { 1390 transitSelectBox.setSelectedItemByName(info.getTransitName()); 1391 } catch (Exception ex) { 1392 log.warn("Transit {} from file not in Transit menu", info.getTransitName()); 1393 JmriJOptionPane.showMessageDialog(initiateFrame, 1394 Bundle.getMessage("TransitWarn", info.getTransitName()), 1395 null, JmriJOptionPane.WARNING_MESSAGE); 1396 } 1397 _TrainsFrom = info.getTrainsFrom(); 1398 switch (_TrainsFrom) { 1399 case TRAINSFROMROSTER: 1400 radioTrainsFromRoster.setSelected(true); 1401 if (!setRosterComboBox(rosterComboBox, info.getTrainName())) { 1402 log.warn("Roster {} from file not in Roster Combo", info.getTrainName()); 1403 JmriJOptionPane.showMessageDialog(initiateFrame, 1404 Bundle.getMessage("TrainWarn", info.getTrainName()), 1405 null, JmriJOptionPane.WARNING_MESSAGE); 1406 } 1407 break; 1408 case TRAINSFROMOPS: 1409 radioTrainsFromOps.setSelected(true); 1410 if (!setTrainComboBox(trainSelectBox, info.getTrainName())) { 1411 log.warn("Train {} from file not in Train Combo", info.getTrainName()); 1412 JmriJOptionPane.showMessageDialog(initiateFrame, 1413 Bundle.getMessage("TrainWarn", info.getTrainName()), 1414 null, JmriJOptionPane.WARNING_MESSAGE); 1415 } 1416 break; 1417 case TRAINSFROMUSER: 1418 radioTrainsFromUser.setSelected(true); 1419 trainNameField.setText(info.getTrainName()); 1420 dccAddressSpinner.setValue(Integer.parseInt(info.getDccAddress())); 1421 break; 1422 case TRAINSFROMSETLATER: 1423 default: 1424 radioTrainsFromSetLater.setSelected(true); 1425 } 1426 trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection()); 1427 inTransitBox.setSelected(info.getTrainInTransit()); 1428 initializeStartingBlockCombo(); 1429 initializeDestinationBlockCombo(); 1430 setComboBox(startingBlockBox, info.getStartBlockName()); 1431 setComboBox(destinationBlockBox, info.getDestinationBlockName()); 1432 prioritySpinner.setValue(info.getPriority()); 1433 resetWhenDoneBox.setSelected(info.getResetWhenDone()); 1434 reverseAtEndBox.setSelected(info.getReverseAtEnd()); 1435 setDelayModeBox(info.getDelayedStart(), delayedStartBox); 1436 //delayedStartBox.setSelected(info.getDelayedStart()); 1437 departureHrSpinner.setValue(info.getDepartureTimeHr()); 1438 departureMinSpinner.setValue(info.getDepartureTimeMin()); 1439 delaySensor.setSelectedItem(info.getDelaySensor()); 1440 resetStartSensorBox.setSelected(info.getResetStartSensor()); 1441 setDelayModeBox(info.getDelayedRestart(), delayedReStartBox); 1442 delayMinSpinner.setValue(info.getRestartDelayMin()); 1443 delayReStartSensor.setSelectedItem(info.getRestartSensor()); 1444 resetRestartSensorBox.setSelected(info.getResetRestartSensor()); 1445 1446 resetStartSensorBox.setSelected(info.getResetStartSensor()); 1447 setDelayModeBox(info.getReverseDelayedRestart(), reverseDelayedRestartType); 1448 delayReverseMinSpinner.setValue(info.getReverseRestartDelayMin()); 1449 delayReverseReStartSensor.setSelectedItem(info.getReverseRestartSensor()); 1450 delayReverseResetSensorBox.setSelected(info.getReverseResetRestartSensor()); 1451 1452 terminateWhenDoneBox.setSelected(info.getTerminateWhenDone()); 1453 nextTrain.setSelectedIndex(-1); 1454 1455 try { 1456 nextTrain.setSelectedItem(info.getNextTrain()); 1457 } catch (Exception ex){ 1458 nextTrain.setSelectedIndex(-1); 1459 } 1460 handleTerminateWhenDoneBoxClick(null); 1461 setComboBox(trainTypeBox, info.getTrainType()); 1462 autoRunBox.setSelected(info.getAutoRun()); 1463 loadAtStartupBox.setSelected(info.getLoadAtStartup()); 1464 setAllocateMethodButtons(info.getAllocationMethod()); 1465 autoTrainInfoToDialog(info); 1466 } 1467 1468 private TrainInfo dialogToTrainInfo(boolean locoOptional) throws IllegalArgumentException { 1469 TrainInfo info = new TrainInfo(); 1470 int index = transitSelectBox.getSelectedIndex(); 1471 if (index < 0) { 1472 throw new IllegalArgumentException(Bundle.getMessage("Error44")); 1473 } else { 1474 info.setTransitName(transitSelectBox.getSelectedItem().getDisplayName()); 1475 info.setTransitId(transitSelectBox.getSelectedItem().getDisplayName()); 1476 } 1477 switch (_TrainsFrom) { 1478 case TRAINSFROMROSTER: 1479 if (rosterComboBox.getSelectedIndex() < 1 ) { 1480 throw new IllegalArgumentException(Bundle.getMessage("Error41")); 1481 } 1482 info.setTrainName(((RosterEntry) rosterComboBox.getSelectedItem()).getId()); 1483 info.setDccAddress(" "); 1484 break; 1485 case TRAINSFROMOPS: 1486 if (trainSelectBox.getSelectedIndex() < 1) { 1487 throw new IllegalArgumentException(Bundle.getMessage("Error42")); 1488 } 1489 info.setTrainName(((Train) trainSelectBox.getSelectedItem()).getId()); 1490 info.setDccAddress(String.valueOf(dccAddressSpinner.getValue())); 1491 break; 1492 case TRAINSFROMUSER: 1493 if (trainNameField.getText().isEmpty()) { 1494 throw new IllegalArgumentException(Bundle.getMessage("Error22")); 1495 } 1496 info.setTrainName(trainNameField.getText()); 1497 info.setDccAddress(String.valueOf(dccAddressSpinner.getValue())); 1498 break; 1499 case TRAINSFROMSETLATER: 1500 default: 1501 info.setTrainName(""); 1502 info.setDccAddress(""); 1503 } 1504 info.setTrainInTransit(inTransitBox.isSelected()); 1505 info.setStartBlockName((String) startingBlockBox.getSelectedItem()); 1506 index = startingBlockBox.getSelectedIndex(); 1507 if (index < 0) { 1508 throw new IllegalArgumentException(Bundle.getMessage("Error13")); 1509 } else { 1510 info.setStartBlockId(startingBlockBoxList.get(index).getDisplayName()); 1511 info.setStartBlockSeq(startingBlockSeqList.get(index).intValue()); 1512 } 1513 info.setDestinationBlockName((String) destinationBlockBox.getSelectedItem()); 1514 index = destinationBlockBox.getSelectedIndex(); 1515 if (index < 0) { 1516 throw new IllegalArgumentException(Bundle.getMessage("Error8")); 1517 } else { 1518 info.setDestinationBlockId(destinationBlockBoxList.get(index).getDisplayName()); 1519 info.setDestinationBlockSeq(destinationBlockSeqList.get(index).intValue()); 1520 } 1521 info.setTrainsFrom(_TrainsFrom); 1522 info.setPriority((Integer) prioritySpinner.getValue()); 1523 info.setTrainDetection(((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value); 1524 info.setResetWhenDone(resetWhenDoneBox.isSelected()); 1525 info.setReverseAtEnd(reverseAtEndBox.isSelected()); 1526 info.setDelayedStart(delayModeFromBox(delayedStartBox)); 1527 info.setDelaySensorName(delaySensor.getSelectedItemDisplayName()); 1528 info.setResetStartSensor(resetStartSensorBox.isSelected()); 1529 info.setDepartureTimeHr((Integer) departureHrSpinner.getValue()); 1530 info.setDepartureTimeMin((Integer) departureMinSpinner.getValue()); 1531 info.setTrainType((String) trainTypeBox.getSelectedItem()); 1532 info.setAutoRun(autoRunBox.isSelected()); 1533 info.setLoadAtStartup(loadAtStartupBox.isSelected()); 1534 info.setAllocateAllTheWay(false); // force to false next field is now used. 1535 if (allocateAllTheWayRadioButton.isSelected()) { 1536 info.setAllocationMethod(ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN); 1537 } else if (allocateBySafeRadioButton.isSelected()) { 1538 info.setAllocationMethod(ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS); 1539 } else { 1540 info.setAllocationMethod((Integer) allocateCustomSpinner.getValue()); 1541 } 1542 info.setDelayedRestart(delayModeFromBox(delayedReStartBox)); 1543 info.setRestartSensorName(delayReStartSensor.getSelectedItemDisplayName()); 1544 info.setResetRestartSensor(resetRestartSensorBox.isSelected()); 1545 info.setRestartDelayMin((Integer) delayMinSpinner.getValue()); 1546 1547 info.setReverseDelayedRestart(delayModeFromBox(reverseDelayedRestartType)); 1548 info.setReverseRestartSensorName(delayReverseReStartSensor.getSelectedItemDisplayName()); 1549 info.setReverseResetRestartSensor(delayReverseResetSensorBox.isSelected()); 1550 info.setReverseRestartDelayMin((Integer) delayReverseMinSpinner.getValue()); 1551 1552 info.setTerminateWhenDone(terminateWhenDoneBox.isSelected()); 1553 if (nextTrain.getSelectedIndex() > 0 ) { 1554 info.setNextTrain((String)nextTrain.getSelectedItem()); 1555 } else { 1556 info.setNextTrain("None"); 1557 } 1558 autoRunItemsToTrainInfo(info); 1559 return info; 1560 } 1561 1562 private boolean setRosterComboBox(RosterEntryComboBox box, String txt) { 1563 boolean found = false; 1564 for (int i = 1; i < box.getItemCount(); i++) { 1565 if (txt.equals(((RosterEntry) box.getItemAt(i)).getId())) { 1566 box.setSelectedIndex(i); 1567 found = true; 1568 break; 1569 } 1570 } 1571 if (!found && box.getItemCount() > 0) { 1572 box.setSelectedIndex(0); 1573 } 1574 return found; 1575 } 1576 1577 // Normalizes a suggested xml file name. Returns null string if a valid name cannot be assembled 1578 private String normalizeXmlFileName(String name) { 1579 if (name.length() < 1) { 1580 return ""; 1581 } 1582 String newName = name; 1583 // strip off .xml or .XML if present 1584 if ((name.endsWith(".xml")) || (name.endsWith(".XML"))) { 1585 newName = name.substring(0, name.length() - 4); 1586 if (newName.length() < 1) { 1587 return ""; 1588 } 1589 } 1590 // replace all non-alphanumeric characters with underscore 1591 newName = newName.replaceAll("[\\W]", "_"); 1592 return (newName + ".xml"); 1593 } 1594 1595 private boolean setTrainComboBox(JComboBox<Object> box, String txt) { 1596 boolean found = false; 1597 for (int i = 1; i < box.getItemCount(); i++) { //skip the select train item 1598 if (txt.equals(box.getItemAt(i).toString())) { 1599 box.setSelectedIndex(i); 1600 found = true; 1601 break; 1602 } 1603 } 1604 if (!found && box.getItemCount() > 0) { 1605 box.setSelectedIndex(0); 1606 } 1607 return found; 1608 } 1609 1610 private boolean setComboBox(JComboBox<String> box, String txt) { 1611 boolean found = false; 1612 for (int i = 0; i < box.getItemCount(); i++) { 1613 if (txt.equals(box.getItemAt(i))) { 1614 box.setSelectedIndex(i); 1615 found = true; 1616 break; 1617 } 1618 } 1619 if (!found && box.getItemCount() > 0) { 1620 box.setSelectedIndex(0); 1621 } 1622 return found; 1623 } 1624 1625 int delayModeFromBox(JComboBox<String> box) { 1626 String mode = (String) box.getSelectedItem(); 1627 int result = jmri.util.StringUtil.getStateFromName(mode, delayedStartInt, delayedStartString); 1628 1629 if (result < 0) { 1630 log.warn("unexpected mode string in turnoutMode: {}", mode); 1631 throw new IllegalArgumentException(); 1632 } 1633 return result; 1634 } 1635 1636 void setDelayModeBox(int mode, JComboBox<String> box) { 1637 String result = jmri.util.StringUtil.getNameFromState(mode, delayedStartInt, delayedStartString); 1638 box.setSelectedItem(result); 1639 } 1640 1641 /** 1642 * The following are for items that are only for automatic running of 1643 * ActiveTrains They are isolated here to simplify changing them in the 1644 * future. 1645 * <ul> 1646 * <li>initializeAutoRunItems - initializes the display of auto run items in 1647 * this window 1648 * <li>initializeAutoRunValues - initializes the values of auto run items 1649 * from values in a saved train info file hideAutoRunItems - hides all auto 1650 * run items in this window showAutoRunItems - shows all auto run items in 1651 * this window 1652 * <li>autoTrainInfoToDialog - gets auto run items from a train info, puts 1653 * values in items, and initializes auto run dialog items 1654 * <li>autoTrainItemsToTrainInfo - copies values of auto run items to train 1655 * info for saving to a file 1656 * <li>readAutoRunItems - reads and checks values of all auto run items. 1657 * returns true if OK, sends appropriate messages and returns false if not 1658 * OK 1659 * <li>setAutoRunItems - sets the user entered auto run items in the new 1660 * AutoActiveTrain 1661 * </ul> 1662 */ 1663 // auto run items in ActivateTrainFrame 1664 private final JPanel pa1 = new JPanel(); 1665 private final JLabel speedFactorLabel = new JLabel(Bundle.getMessage("SpeedFactorLabel")); 1666 private final JSpinner speedFactorSpinner = new JSpinner(); 1667 private final JLabel maxSpeedLabel = new JLabel(Bundle.getMessage("MaxSpeedLabel")); 1668 private final JSpinner maxSpeedSpinner = new JSpinner(); 1669 private final JPanel pa2 = new JPanel(); 1670 private final JLabel rampRateLabel = new JLabel(Bundle.getMessage("RampRateBoxLabel")); 1671 private final JComboBox<String> rampRateBox = new JComboBox<>(); 1672 private final JPanel pa2a = new JPanel(); 1673 private final JLabel useSpeedProfileLabel = new JLabel(Bundle.getMessage("UseSpeedProfileLabel")); 1674 private final JCheckBox useSpeedProfileCheckBox = new JCheckBox( ); 1675 private final JLabel stopBySpeedProfileLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileLabel")); 1676 private final JCheckBox stopBySpeedProfileCheckBox = new JCheckBox( ); 1677 private final JLabel stopBySpeedProfileAdjustLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileAdjustLabel")); 1678 private final JSpinner stopBySpeedProfileAdjustSpinner = new JSpinner(); 1679 private final JPanel pa3 = new JPanel(); 1680 private final JCheckBox soundDecoderBox = new JCheckBox(Bundle.getMessage("SoundDecoder")); 1681 private final JCheckBox runInReverseBox = new JCheckBox(Bundle.getMessage("RunInReverse")); 1682 private final JPanel pa4 = new JPanel(); 1683 protected static class TrainDetectionJCombo extends JComboBox<TrainDetectionItem> { 1684 public void setSelectedItemByValue(TrainDetection var) { 1685 for ( int ix = 0; ix < getItemCount() ; ix ++ ) { 1686 if (getItemAt(ix).value == var) { 1687 this.setSelectedIndex(ix); 1688 break; 1689 } 1690 } 1691 } 1692 } 1693 public final TrainDetectionJCombo trainDetectionComboBox 1694 = new TrainDetectionJCombo(); 1695 private final JLabel trainDetectionLabel = new JLabel(Bundle.getMessage("TrainDetection")); 1696 private final JLabel trainLengthLabel = new JLabel(Bundle.getMessage("MaxTrainLengthLabel")); 1697 private final JSpinner maxTrainLengthSpinner = new JSpinner(); // initialized later 1698 // auto run variables 1699 float _speedFactor = 1.0f; 1700 float _maxSpeed = 0.6f; 1701 int _rampRate = AutoActiveTrain.RAMP_NONE; 1702 TrainDetection _trainDetection = TrainDetection.TRAINDETECTION_HEADONLY; 1703 boolean _runInReverse = false; 1704 boolean _soundDecoder = false; 1705 float _maxTrainLength = 200.0f; 1706 boolean _stopBySpeedProfile = false; 1707 float _stopBySpeedProfileAdjust = 1.0f; 1708 boolean _useSpeedProfile = true; 1709 String _nextTrain = ""; 1710 1711 private void setAutoRunDefaults() { 1712 _speedFactor = 1.0f; 1713 _maxSpeed = 0.6f; 1714 _rampRate = AutoActiveTrain.RAMP_NONE; 1715 _runInReverse = false; 1716 _soundDecoder = false; 1717 _maxTrainLength = 100.0f; 1718 _stopBySpeedProfile = false; 1719 _stopBySpeedProfileAdjust = 1.0f; 1720 _useSpeedProfile = true; 1721 _nextTrain = ""; 1722 1723 } 1724 1725 private void initializeAutoRunItems() { 1726 initializeRampCombo(); 1727 pa1.setLayout(new FlowLayout()); 1728 pa1.add(speedFactorLabel); 1729 speedFactorSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(2.0f), Float.valueOf(0.01f))); 1730 speedFactorSpinner.setEditor(new JSpinner.NumberEditor(speedFactorSpinner, "# %")); 1731 pa1.add(speedFactorSpinner); 1732 speedFactorSpinner.setToolTipText(Bundle.getMessage("SpeedFactorHint")); 1733 pa1.add(new JLabel(" ")); 1734 pa1.add(maxSpeedLabel); 1735 maxSpeedSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(2.0f), Float.valueOf(0.01f))); 1736 maxSpeedSpinner.setEditor(new JSpinner.NumberEditor(maxSpeedSpinner, "# %")); 1737 pa1.add(maxSpeedSpinner); 1738 maxSpeedSpinner.setToolTipText(Bundle.getMessage("MaxSpeedHint")); 1739 initiatePane.add(pa1); 1740 pa2.setLayout(new FlowLayout()); 1741 pa2.add(rampRateLabel); 1742 pa2.add(rampRateBox); 1743 rampRateBox.setToolTipText(Bundle.getMessage("RampRateBoxHint")); 1744 pa2.add(useSpeedProfileLabel); 1745 pa2.add(useSpeedProfileCheckBox); 1746 useSpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint")); 1747 initiatePane.add(pa2); 1748 pa2a.setLayout(new FlowLayout()); 1749 pa2a.add(stopBySpeedProfileLabel); 1750 pa2a.add(stopBySpeedProfileCheckBox); 1751 stopBySpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint")); // reuse identical hint for Stop 1752 pa2a.add(stopBySpeedProfileAdjustLabel); 1753 stopBySpeedProfileAdjustSpinner.setModel(new SpinnerNumberModel( Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(5.0f), Float.valueOf(0.01f))); 1754 stopBySpeedProfileAdjustSpinner.setEditor(new JSpinner.NumberEditor(stopBySpeedProfileAdjustSpinner, "# %")); 1755 pa2a.add(stopBySpeedProfileAdjustSpinner); 1756 stopBySpeedProfileAdjustSpinner.setToolTipText(Bundle.getMessage("StopBySpeedProfileAdjustHint")); 1757 initiatePane.add(pa2a); 1758 pa3.setLayout(new FlowLayout()); 1759 pa3.add(soundDecoderBox); 1760 soundDecoderBox.setToolTipText(Bundle.getMessage("SoundDecoderBoxHint")); 1761 pa3.add(new JLabel(" ")); 1762 pa3.add(runInReverseBox); 1763 runInReverseBox.setToolTipText(Bundle.getMessage("RunInReverseBoxHint")); 1764 initiatePane.add(pa3); 1765 pa4.setLayout(new FlowLayout()); 1766 pa4.add(trainLengthLabel); 1767 maxTrainLengthSpinner.setModel(new SpinnerNumberModel(Float.valueOf(18.0f), Float.valueOf(0.0f), Float.valueOf(10000.0f), Float.valueOf(0.5f))); 1768 maxTrainLengthSpinner.setEditor(new JSpinner.NumberEditor(maxTrainLengthSpinner, "###0.0")); 1769 pa4.add(maxTrainLengthSpinner); 1770 boolean unitIsMeter = InstanceManager.getDefault(DispatcherFrame.class).getUseScaleMeters(); // read from user setting 1771 maxTrainLengthSpinner.setToolTipText(Bundle.getMessage("MaxTrainLengthHint", 1772 (unitIsMeter ? Bundle.getMessage("ScaleMeters") : Bundle.getMessage("ScaleFeet")))); // won't be updated while Dispatcher is open 1773 initiatePane.add(pa4); 1774 hideAutoRunItems(); // initialize with auto run items hidden 1775 initializeAutoRunValues(); 1776 } 1777 1778 private void initializeAutoRunValues() { 1779 speedFactorSpinner.setValue(_speedFactor); 1780 maxSpeedSpinner.setValue(_maxSpeed); 1781 rampRateBox.setSelectedIndex(_rampRate); 1782 soundDecoderBox.setSelected(_soundDecoder); 1783 runInReverseBox.setSelected(_runInReverse); 1784 useSpeedProfileCheckBox.setSelected(_useSpeedProfile); 1785 stopBySpeedProfileAdjustSpinner.setValue(_stopBySpeedProfileAdjust); 1786 stopBySpeedProfileCheckBox.setSelected(_stopBySpeedProfile); 1787 maxTrainLengthSpinner.setValue(Math.round(_maxTrainLength * 2) * 0.5f); // set in spinner as 0.5 increments 1788 1789 } 1790 1791 private void hideAutoRunItems() { 1792 pa1.setVisible(false); 1793 pa2.setVisible(false); 1794 pa2a.setVisible(false); 1795 pa3.setVisible(false); 1796 pa4.setVisible(false); 1797 } 1798 1799 private void showAutoRunItems() { 1800 pa1.setVisible(true); 1801 pa2.setVisible(true); 1802 pa2a.setVisible(true); 1803 pa3.setVisible(true); 1804 pa4.setVisible(true); 1805 } 1806 1807 private void autoTrainInfoToDialog(TrainInfo info) { 1808 speedFactorSpinner.setValue(info.getSpeedFactor()); 1809 maxSpeedSpinner.setValue(info.getMaxSpeed()); 1810 setComboBox(rampRateBox, info.getRampRate()); 1811 trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection()); 1812 runInReverseBox.setSelected(info.getRunInReverse()); 1813 soundDecoderBox.setSelected(info.getSoundDecoder()); 1814 maxTrainLengthSpinner.setValue(info.getMaxTrainLength()); 1815 useSpeedProfileCheckBox.setSelected(info.getUseSpeedProfile()); 1816 stopBySpeedProfileCheckBox.setSelected(info.getStopBySpeedProfile()); 1817 stopBySpeedProfileAdjustSpinner.setValue(info.getStopBySpeedProfileAdjust()); 1818 if (autoRunBox.isSelected()) { 1819 showAutoRunItems(); 1820 } else { 1821 hideAutoRunItems(); 1822 } 1823 initiateFrame.pack(); 1824 } 1825 1826 private void autoRunItemsToTrainInfo(TrainInfo info) { 1827 info.setSpeedFactor((float) speedFactorSpinner.getValue()); 1828 info.setMaxSpeed((float) maxSpeedSpinner.getValue()); 1829 info.setRampRate((String) rampRateBox.getSelectedItem()); 1830 info.setRunInReverse(runInReverseBox.isSelected()); 1831 info.setSoundDecoder(soundDecoderBox.isSelected()); 1832 info.setMaxTrainLength((float) maxTrainLengthSpinner.getValue()); 1833 // Only use speed profile values if enabled 1834 if (useSpeedProfileCheckBox.isEnabled()) { 1835 info.setUseSpeedProfile(useSpeedProfileCheckBox.isSelected()); 1836 info.setStopBySpeedProfile(stopBySpeedProfileCheckBox.isSelected()); 1837 info.setStopBySpeedProfileAdjust((float) stopBySpeedProfileAdjustSpinner.getValue()); 1838 } else { 1839 info.setUseSpeedProfile(false); 1840 info.setStopBySpeedProfile(false); 1841 info.setStopBySpeedProfileAdjust(1.0f); 1842 } 1843 } 1844 1845 private boolean readAutoRunItems() { 1846 boolean success = true; 1847 _speedFactor = (float) speedFactorSpinner.getValue(); 1848 _maxSpeed = (float) maxSpeedSpinner.getValue(); 1849 _rampRate = rampRateBox.getSelectedIndex(); 1850 _trainDetection = ((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value; 1851 _runInReverse = runInReverseBox.isSelected(); 1852 _soundDecoder = soundDecoderBox.isSelected(); 1853 _maxTrainLength = (float) maxTrainLengthSpinner.getValue(); 1854 _useSpeedProfile = useSpeedProfileCheckBox.isSelected(); 1855 _stopBySpeedProfile = stopBySpeedProfileCheckBox.isSelected(); 1856 if (_stopBySpeedProfile) { 1857 _stopBySpeedProfileAdjust = (Float) stopBySpeedProfileAdjustSpinner.getValue(); 1858 } 1859 if (nextTrain.getSelectedIndex() < 0) { 1860 _nextTrain=""; 1861 } else { 1862 _nextTrain = (String)nextTrain.getSelectedItem(); 1863 } 1864 return success; 1865 } 1866 1867 private void setAutoRunItems(AutoActiveTrain aaf) { 1868 aaf.setSpeedFactor(_speedFactor); 1869 aaf.setMaxSpeed(_maxSpeed); 1870 aaf.setRampRate(_rampRate); 1871 aaf.setRunInReverse(_runInReverse); 1872 aaf.setSoundDecoder(_soundDecoder); 1873 aaf.setMaxTrainLength(_maxTrainLength); 1874 aaf.setStopBySpeedProfile(_stopBySpeedProfile); 1875 aaf.setStopBySpeedProfileAdjust(_stopBySpeedProfileAdjust); 1876 aaf.setUseSpeedProfile(_useSpeedProfile); 1877 } 1878 1879 private void initializeRampCombo() { 1880 rampRateBox.removeAllItems(); 1881 rampRateBox.addItem(Bundle.getMessage("RAMP_NONE")); 1882 rampRateBox.addItem(Bundle.getMessage("RAMP_FAST")); 1883 rampRateBox.addItem(Bundle.getMessage("RAMP_MEDIUM")); 1884 rampRateBox.addItem(Bundle.getMessage("RAMP_MED_SLOW")); 1885 rampRateBox.addItem(Bundle.getMessage("RAMP_SLOW")); 1886 rampRateBox.addItem(Bundle.getMessage("RAMP_SPEEDPROFILE")); 1887 // Note: the order above must correspond to the numbers in AutoActiveTrain.java 1888 } 1889 1890 /** 1891 * Sets up the RadioButtons and visability of spinner for the allocation method 1892 * 1893 * @param value 0, Allocate by Safe spots, -1, allocate as far as possible Any 1894 * other value the number of sections to allocate 1895 */ 1896 private void setAllocateMethodButtons(int value) { 1897 switch (value) { 1898 case ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS: 1899 allocateBySafeRadioButton.setSelected(true); 1900 allocateCustomSpinner.setVisible(false); 1901 break; 1902 case ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN: 1903 allocateAllTheWayRadioButton.setSelected(true); 1904 allocateCustomSpinner.setVisible(false); 1905 break; 1906 default: 1907 allocateNumberOfBlocks.setSelected(true); 1908 allocateCustomSpinner.setVisible(true); 1909 allocateCustomSpinner.setValue(value); 1910 } 1911 } 1912 1913 /* 1914 * ComboBox item. 1915 */ 1916 protected static class TrainDetectionItem { 1917 private String key; 1918 private TrainDetection value; 1919 public TrainDetectionItem(String text, TrainDetection trainDetection ) { 1920 this.key = text; 1921 this.value = trainDetection; 1922 } 1923 @Override 1924 public String toString() 1925 { 1926 return key; 1927 } 1928 public String getKey() 1929 { 1930 return key; 1931 } 1932 public TrainDetection getValue() 1933 { 1934 return value; 1935 } 1936 } 1937 1938 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActivateTrainFrame.class); 1939 1940}