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(true); 661 trainNameField.setVisible(true); 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(true); 671 trainNameField.setVisible(true); 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(true); 694 trainNameField.setVisible(true); 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 trainNameField.setText(r.titleString()); 783 if (r.getAttribute("DispatcherTrainType") != null && !r.getAttribute("DispatcherTrainType").equals("")) { 784 trainTypeBox.setSelectedItem(r.getAttribute("DispatcherTrainType")); 785 } 786 } else { 787 setSpeedProfileOptions(false); 788 } 789 } 790 791 private boolean checkResetWhenDone() { 792 if ((!reverseAtEndBox.isSelected()) && resetWhenDoneBox.isSelected() 793 && (!selectedTransit.canBeResetWhenDone())) { 794 resetWhenDoneBox.setSelected(false); 795 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle 796 .getMessage("NoResetMessage"), Bundle.getMessage("MessageTitle"), 797 JmriJOptionPane.INFORMATION_MESSAGE); 798 return false; 799 } 800 return true; 801 } 802 803 private void handleDelayStartClick(ActionEvent e) { 804 departureHrSpinner.setVisible(false); 805 departureMinSpinner.setVisible(false); 806 departureTimeLabel.setVisible(false); 807 departureSepLabel.setVisible(false); 808 delaySensor.setVisible(false); 809 resetStartSensorBox.setVisible(false); 810 if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 811 departureHrSpinner.setVisible(true); 812 departureMinSpinner.setVisible(true); 813 departureTimeLabel.setVisible(true); 814 departureSepLabel.setVisible(true); 815 } else if (delayedStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 816 delaySensor.setVisible(true); 817 resetStartSensorBox.setVisible(true); 818 } 819 initiateFrame.pack(); // to fit extra hh:mm in window 820 } 821 822 private void handleResetWhenDoneClick(ActionEvent e) { 823 delayMinSpinner.setVisible(false); 824 delayMinLabel.setVisible(false); 825 delayedReStartLabel.setVisible(false); 826 delayedReStartBox.setVisible(false); 827 delayReStartSensorLabel.setVisible(false); 828 delayReStartSensor.setVisible(false); 829 resetRestartSensorBox.setVisible(false); 830 if (resetWhenDoneBox.isSelected()) { 831 delayedReStartLabel.setVisible(true); 832 delayedReStartBox.setVisible(true); 833 terminateWhenDoneBox.setSelected(false); 834 if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 835 delayMinSpinner.setVisible(true); 836 delayMinLabel.setVisible(true); 837 } else if (delayedReStartBox.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 838 delayReStartSensor.setVisible(true); 839 delayReStartSensorLabel.setVisible(true); 840 resetRestartSensorBox.setVisible(true); 841 } 842 } else { 843 terminateWhenDoneBox.setEnabled(true); 844 } 845 initiateFrame.pack(); 846 } 847 848 private void handleTerminateWhenDoneBoxClick(ActionEvent e) { 849 if (terminateWhenDoneBox.isSelected()) { 850 refreshNextTrainCombo(); 851 resetWhenDoneBox.setSelected(false); 852 terminateWhenDoneDetails.setVisible(true); 853 } else { 854 terminateWhenDoneDetails.setVisible(false); 855 // leave it 856 //nextTrain.setSelectedItem(""); 857 } 858 } 859 private void handleReverseAtEndBoxClick(ActionEvent e) { 860 delayReverseMinSpinner.setVisible(false); 861 delayReverseMinLabel.setVisible(false); 862 delayReverseReStartLabel.setVisible(false); 863 reverseDelayedRestartType.setVisible(false); 864 delayReverseReStartSensorLabel.setVisible(false); 865 delayReverseReStartSensor.setVisible(false); 866 delayReverseResetSensorBox.setVisible(false); 867 if (reverseAtEndBox.isSelected()) { 868 delayReverseReStartLabel.setVisible(true); 869 reverseDelayedRestartType.setVisible(true); 870 if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartTimed"))) { 871 delayReverseMinSpinner.setVisible(true); 872 delayReverseMinLabel.setVisible(true); 873 } else if (reverseDelayedRestartType.getSelectedItem().equals(Bundle.getMessage("DelayedStartSensor"))) { 874 delayReverseReStartSensor.setVisible(true); 875 delayReStartSensorLabel.setVisible(true); 876 delayReverseResetSensorBox.setVisible(true); 877 } 878 } 879 initiateFrame.pack(); 880 881 if (resetWhenDoneBox.isSelected()) { 882 terminateWhenDoneBox.setSelected(false); 883 terminateWhenDoneBox.setEnabled(false); 884 } else { 885 terminateWhenDoneBox.setEnabled(true); 886 } 887 } 888 889 private void handleAutoRunClick(ActionEvent e) { 890 if (autoRunBox.isSelected()) { 891 showAutoRunItems(); 892 } else { 893 hideAutoRunItems(); 894 } 895 initiateFrame.pack(); 896 } 897 898 private void handleStartingBlockSelectionChanged(ActionEvent e) { 899 initializeDestinationBlockCombo(); 900 initiateFrame.pack(); 901 } 902 903 private void handleAllocateAllTheWayButtonChanged(ActionEvent e) { 904 allocateCustomSpinner.setVisible(false); 905 } 906 907 private void handleAllocateBySafeButtonChanged(ActionEvent e) { 908 allocateCustomSpinner.setVisible(false); 909 } 910 911 private void handleAllocateNumberOfBlocksButtonChanged(ActionEvent e) { 912 allocateCustomSpinner.setVisible(true); 913 } 914 915 private void cancelInitiateTrain(ActionEvent e) { 916 _dispatcher.newTrainDone(null); 917 } 918 919 /** 920 * Handles press of "Add New Train" button by edit-checking populated values 921 * then (if no errors) creating an ActiveTrain and (optionally) an 922 * AutoActiveTrain 923 */ 924 private void addNewTrain(ActionEvent e) { 925 // get information 926 if (selectedTransit == null) { 927 // no transits available 928 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error15"), 929 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 930 cancelInitiateTrain(null); 931 return; 932 } 933 String transitName = selectedTransit.getDisplayName(); 934 String trainName = ""; 935 int index = startingBlockBox.getSelectedIndex(); 936 if (index < 0) { 937 return; 938 } 939 String startBlockName = startingBlockBoxList.get(index).getDisplayName(); 940 int startBlockSeq = startingBlockSeqList.get(index).intValue(); 941 index = destinationBlockBox.getSelectedIndex(); 942 if (index < 0) { 943 return; 944 } 945 String endBlockName = destinationBlockBoxList.get(index).getDisplayName(); 946 int endBlockSeq = destinationBlockSeqList.get(index).intValue(); 947 boolean autoRun = autoRunBox.isSelected(); 948 if (!checkResetWhenDone()) { 949 return; 950 } 951 boolean resetWhenDone = resetWhenDoneBox.isSelected(); 952 boolean reverseAtEnd = reverseAtEndBox.isSelected(); 953 index = trainDetectionComboBox.getSelectedIndex(); 954 if (index < 0) { 955 return; 956 } 957 TrainDetection trainDetection = ((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value; 958 int allocateMethod = 3; 959 if (allocateAllTheWayRadioButton.isSelected()) { 960 allocateMethod = ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN; 961 } else if (allocateBySafeRadioButton.isSelected()) { 962 allocateMethod = ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS; 963 } else { 964 allocateMethod = (Integer) allocateCustomSpinner.getValue(); 965 } 966 int delayedStart = delayModeFromBox(delayedStartBox); 967 int delayedReStart = delayModeFromBox(delayedReStartBox); 968 int delayedReverseReStart = delayModeFromBox(reverseDelayedRestartType); 969 int departureTimeHours = 8; 970 departureTimeHours = (Integer) departureHrSpinner.getValue(); 971 int departureTimeMinutes = 8; 972 departureTimeMinutes = (Integer) departureMinSpinner.getValue(); 973 int delayRestartMinutes = 0; 974 delayRestartMinutes = (Integer) delayMinSpinner.getValue(); 975 if ((delayRestartMinutes < 0)) { 976 JmriJOptionPane.showMessageDialog(initiateFrame, delayMinSpinner.getValue(), 977 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 978 log.warn("Range error in Delay Restart Time Minutes field"); 979 return; 980 } 981 int delayReverseRestartMinutes = 0; 982 delayReverseRestartMinutes = (Integer) delayReverseMinSpinner.getValue(); 983 if ((delayReverseRestartMinutes < 0)) { 984 JmriJOptionPane.showMessageDialog(initiateFrame, delayReverseMinSpinner.getValue(), 985 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 986 log.warn("Range error in Reverse Delay Restart Time Minutes field"); 987 return; 988 } 989 int tSource = 0; 990 String dccAddress = "unknown"; 991 switch (_TrainsFrom) { 992 case TRAINSFROMROSTER: 993 index = rosterComboBox.getSelectedIndex(); 994 if (index < 1) { // first item is the "Select Loco" message 995 // no train selected 996 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error41"), 997 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 998 return; 999 } 1000 RosterEntry r = (RosterEntry) rosterComboBox.getSelectedItem(); 1001 dccAddress = r.getDccAddress(); 1002 if (trainNameField.getText().isEmpty()) { 1003 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1004 "Error45", dccAddress), Bundle.getMessage("ErrorTitle"), 1005 JmriJOptionPane.ERROR_MESSAGE); 1006 return; 1007 } 1008 trainName=trainNameField.getText(); 1009 if (!_dispatcher.isTrainFree(trainName)) { 1010 // train name is already in use by an Active Train 1011 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1012 "Error24", trainName), Bundle.getMessage("ErrorTitle"), 1013 JmriJOptionPane.ERROR_MESSAGE); 1014 return; 1015 } 1016 trainName = trainNameField.getText(); 1017 if (!isAddressFree(r.getDccLocoAddress().getNumber())) { 1018 // DCC address is already in use by an Active Train 1019 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1020 "Error40", dccAddress), Bundle.getMessage("ErrorTitle"), 1021 JmriJOptionPane.ERROR_MESSAGE); 1022 return; 1023 } 1024 1025 tSource = ActiveTrain.ROSTER; 1026 1027 if (trainTypeBox.getSelectedIndex() != 0 && 1028 (r.getAttribute("DispatcherTrainType") == null || 1029 !r.getAttribute("DispatcherTrainType").equals("" + trainTypeBox.getSelectedItem()))) { 1030 r.putAttribute("DispatcherTrainType", "" + trainTypeBox.getSelectedItem()); 1031 r.updateFile(); 1032 Roster.getDefault().writeRoster(); 1033 } 1034 break; 1035 case TRAINSFROMOPS: 1036 tSource = ActiveTrain.OPERATIONS; 1037 index = trainSelectBox.getSelectedIndex(); 1038 if (index < 1) { // first item is Select Train 1039 // Train not selected 1040 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error42"), 1041 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1042 return; 1043 } 1044 if (trainNameField.getText().isEmpty()) { 1045 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1046 "Error45", dccAddress), Bundle.getMessage("ErrorTitle"), 1047 JmriJOptionPane.ERROR_MESSAGE); 1048 return; 1049 } 1050 if (!_dispatcher.isTrainFree(trainName)) { 1051 // train name is already in use by an Active Train 1052 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1053 "Error24", trainName), Bundle.getMessage("ErrorTitle"), 1054 JmriJOptionPane.ERROR_MESSAGE); 1055 return; 1056 } 1057 trainName = trainSelectBox.getSelectedItem().toString(); 1058 dccAddress = getDCCAddressFromSpinner(); 1059 if (dccAddress == null) { 1060 return; 1061 } 1062 break; 1063 case TRAINSFROMUSER: 1064 trainName = trainNameField.getText(); 1065 if ((trainName == null) || trainName.equals("")) { 1066 // no train name entered 1067 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error14"), 1068 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1069 return; 1070 } 1071 if (trainNameField.getText().isEmpty()) { 1072 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1073 "Error45", dccAddress), Bundle.getMessage("ErrorTitle"), 1074 JmriJOptionPane.ERROR_MESSAGE); 1075 return; 1076 } 1077 if (!_dispatcher.isTrainFree(trainName)) { 1078 // train name is already in use by an Active Train 1079 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1080 "Error24", trainName), Bundle.getMessage("ErrorTitle"), 1081 JmriJOptionPane.ERROR_MESSAGE); 1082 return; 1083 } 1084 dccAddress = getDCCAddressFromSpinner(); 1085 if (dccAddress == null) { 1086 return; 1087 } 1088 tSource = ActiveTrain.USER; 1089 break; 1090 case TRAINSFROMSETLATER: 1091 default: 1092 trainName = ""; 1093 } 1094 int priority = 5; 1095 priority = (Integer) prioritySpinner.getValue(); 1096 int trainType = trainTypeBox.getSelectedIndex(); 1097 if (autoRunBox.isSelected()) { 1098 if (!readAutoRunItems()) { 1099 return; 1100 } 1101 } 1102 1103 // create a new Active Train 1104 ActiveTrain at = _dispatcher.createActiveTrain(transitName, trainName, tSource, startBlockName, 1105 startBlockSeq, endBlockName, endBlockSeq, autoRun, dccAddress, priority, 1106 resetWhenDone, reverseAtEnd, true, initiateFrame, allocateMethod); 1107 if (at == null) { 1108 return; // error message sent by createActiveTrain 1109 } 1110 if (tSource == ActiveTrain.ROSTER) { 1111 at.setRosterEntry((RosterEntry)rosterComboBox.getSelectedItem()); 1112 } 1113 at.setTrainDetection(trainDetection); 1114 at.setAllocateMethod(allocateMethod); 1115 at.setDelayedStart(delayedStart); 1116 at.setDelayedRestart(delayedReStart); 1117 at.setDepartureTimeHr(departureTimeHours); 1118 at.setDepartureTimeMin(departureTimeMinutes); 1119 at.setRestartDelay(delayRestartMinutes); 1120 at.setDelaySensor(delaySensor.getSelectedItem()); 1121 at.setReverseDelayRestart(delayedReverseReStart); 1122 at.setReverseRestartDelay(delayReverseRestartMinutes); 1123 at.setReverseDelaySensor(delayReverseReStartSensor.getSelectedItem()); 1124 at.setReverseResetRestartSensor(delayReverseResetSensorBox.isSelected()); 1125 if ((_dispatcher.isFastClockTimeGE(departureTimeHours, departureTimeMinutes) && delayedStart != ActiveTrain.SENSORDELAY) 1126 || delayedStart == ActiveTrain.NODELAY) { 1127 at.setStarted(); 1128 } 1129 at.setRestartSensor(delayReStartSensor.getSelectedItem()); 1130 at.setResetRestartSensor(resetRestartSensorBox.isSelected()); 1131 at.setTrainType(trainType); 1132 at.setTerminateWhenDone(terminateWhenDoneBox.isSelected()); 1133 at.setNextTrain(_nextTrain); 1134 if (autoRunBox.isSelected()) { 1135 AutoActiveTrain aat = new AutoActiveTrain(at); 1136 setAutoRunItems(aat); 1137 _dispatcher.getAutoTrainsFrame().addAutoActiveTrain(aat); 1138 if (!aat.initialize()) { 1139 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1140 "Error27", at.getTrainName()), Bundle.getMessage("MessageTitle"), 1141 JmriJOptionPane.INFORMATION_MESSAGE); 1142 } 1143 } 1144 _dispatcher.allocateNewActiveTrain(at); 1145 _dispatcher.newTrainDone(at); 1146 } 1147 1148 private String getDCCAddressFromSpinner() { 1149 int address = (Integer) dccAddressSpinner.getValue(); // SpinnerNumberModel 1150 // limits 1151 // address to 1152 // 1 - 9999 1153 // inclusive 1154 if (!isAddressFree(address)) { 1155 // DCC address is already in use by an Active Train 1156 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage( 1157 "Error40", address), Bundle.getMessage("ErrorTitle"), 1158 JmriJOptionPane.ERROR_MESSAGE); 1159 return null; 1160 } 1161 return String.valueOf(address); 1162 } 1163 1164 private void initializeFreeTransitsCombo(List<Transit> transitList) { 1165 Set<Transit> excludeTransits = new HashSet<>(); 1166 for (Transit t : _TransitManager.getNamedBeanSet()) { 1167 if (t.getState() != Transit.IDLE) { 1168 excludeTransits.add(t); 1169 } 1170 } 1171 transitSelectBox.setExcludedItems(excludeTransits); 1172 JComboBoxUtil.setupComboBoxMaxRows(transitSelectBox); 1173 1174 if (transitSelectBox.getItemCount() > 0) { 1175 transitSelectBox.setSelectedIndex(0); 1176 selectedTransit = transitSelectBox.getItemAt(0); 1177 } else { 1178 selectedTransit = null; 1179 } 1180 } 1181 1182 private void initializeFreeRosterEntriesCombo() { 1183 rosterComboBox.update(); 1184 // remove used entries 1185 for (int ix = rosterComboBox.getItemCount() - 1; ix > 1; ix--) { // remove from back first item is the "select loco" message 1186 if ( !isAddressFree( ((RosterEntry)rosterComboBox.getItemAt(ix)).getDccLocoAddress().getNumber() ) ) { 1187 rosterComboBox.removeItemAt(ix); 1188 } 1189 } 1190 } 1191 1192 private void initializeFreeTrainsCombo() { 1193 ActionListener[] als = trainSelectBox.getActionListeners(); 1194 for ( ActionListener al: als) { 1195 trainSelectBox.removeActionListener(al); 1196 } 1197 trainSelectBox.removeAllItems(); 1198 trainSelectBox.addItem("Select Train"); 1199 // initialize free trains from operations 1200 List<Train> trains = jmri.InstanceManager.getDefault(TrainManager.class).getTrainsByNameList(); 1201 if (trains.size() > 0) { 1202 for (int i = 0; i < trains.size(); i++) { 1203 Train t = trains.get(i); 1204 if (t != null) { 1205 String tName = t.getName(); 1206 if (_dispatcher.isTrainFree(tName)) { 1207 trainSelectBox.addItem(t); 1208 } 1209 } 1210 } 1211 } 1212 for ( ActionListener al: als) { 1213 trainSelectBox.addActionListener(al); 1214 } 1215 } 1216 1217 /** 1218 * Sets the labels and inputs for speed profile running 1219 * @param b True if the roster entry has valid speed profile else false 1220 */ 1221 private void setSpeedProfileOptions(boolean b) { 1222 useSpeedProfileLabel.setEnabled(b); 1223 useSpeedProfileCheckBox.setEnabled(b); 1224 stopBySpeedProfileLabel.setEnabled(b); 1225 stopBySpeedProfileCheckBox.setEnabled(b); 1226 stopBySpeedProfileAdjustLabel.setEnabled(b); 1227 stopBySpeedProfileAdjustSpinner.setEnabled(b); 1228 if (!b) { 1229 useSpeedProfileCheckBox.setSelected(false); 1230 stopBySpeedProfileCheckBox.setSelected(false); 1231 _useSpeedProfile = false; 1232 _stopBySpeedProfile = false; 1233 } 1234 } 1235 1236 1237 private boolean isAddressFree(int addr) { 1238 for (int j = 0; j < _ActiveTrainsList.size(); j++) { 1239 ActiveTrain at = _ActiveTrainsList.get(j); 1240 if (addr == Integer.parseInt(at.getDccAddress())) { 1241 return false; 1242 } 1243 } 1244 return true; 1245 } 1246 1247 private void initializeStartingBlockCombo() { 1248 startingBlockBox.removeAllItems(); 1249 startingBlockBoxList.clear(); 1250 if (!inTransitBox.isSelected() && selectedTransit.getEntryBlocksList().isEmpty()) { 1251 inTransitBox.setSelected(true); 1252 } 1253 if (inTransitBox.isSelected()) { 1254 startingBlockBoxList = selectedTransit.getInternalBlocksList(); 1255 } else { 1256 startingBlockBoxList = selectedTransit.getEntryBlocksList(); 1257 } 1258 startingBlockSeqList = selectedTransit.getBlockSeqList(); 1259 boolean found = false; 1260 for (int i = 0; i < startingBlockBoxList.size(); i++) { 1261 Block b = startingBlockBoxList.get(i); 1262 int seq = startingBlockSeqList.get(i).intValue(); 1263 startingBlockBox.addItem(getBlockName(b) + "-" + seq); 1264 if (!found && b.getState() == Block.OCCUPIED) { 1265 startingBlockBox.setSelectedItem(getBlockName(b) + "-" + seq); 1266 found = true; 1267 } 1268 } 1269 JComboBoxUtil.setupComboBoxMaxRows(startingBlockBox); 1270 } 1271 1272 private void initializeDestinationBlockCombo() { 1273 destinationBlockBox.removeAllItems(); 1274 destinationBlockBoxList.clear(); 1275 int index = startingBlockBox.getSelectedIndex(); 1276 if (index < 0) { 1277 return; 1278 } 1279 Block startBlock = startingBlockBoxList.get(index); 1280 destinationBlockBoxList = selectedTransit.getDestinationBlocksList( 1281 startBlock, inTransitBox.isSelected()); 1282 destinationBlockSeqList = selectedTransit.getDestBlocksSeqList(); 1283 for (int i = 0; i < destinationBlockBoxList.size(); i++) { 1284 Block b = destinationBlockBoxList.get(i); 1285 String bName = getBlockName(b); 1286 if (selectedTransit.getBlockCount(b) > 1) { 1287 int seq = destinationBlockSeqList.get(i).intValue(); 1288 bName = bName + "-" + seq; 1289 } 1290 destinationBlockBox.addItem(bName); 1291 } 1292 JComboBoxUtil.setupComboBoxMaxRows(destinationBlockBox); 1293 } 1294 1295 private String getBlockName(Block b) { 1296 if (b != null) { 1297 return b.getDisplayName(); 1298 } 1299 return " "; 1300 } 1301 1302 protected void showActivateFrame() { 1303 if (initiateFrame != null) { 1304 initializeFreeTransitsCombo(new ArrayList<Transit>()); 1305 initiateFrame.setVisible(true); 1306 } else { 1307 _dispatcher.newTrainDone(null); 1308 } 1309 } 1310 1311 public void showActivateFrame(RosterEntry re) { 1312 showActivateFrame(); 1313 } 1314 1315 private void loadTrainInfo(ActionEvent e) { 1316 String[] names = _tiFile.getTrainInfoFileNames(); 1317 TrainInfo info = null; 1318 if (names.length > 0) { 1319 //prompt user to select a single train info filename from directory list 1320 Object selName = JmriJOptionPane.showInputDialog(initiateFrame, 1321 Bundle.getMessage("LoadTrainChoice"), Bundle.getMessage("LoadTrainTitle"), 1322 JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]); 1323 if ((selName == null) || (((String) selName).equals(""))) { 1324 return; 1325 } 1326 //read xml data from selected filename and move it into the new train dialog box 1327 _trainInfoName = (String) selName; 1328 try { 1329 info = _tiFile.readTrainInfo((String) selName); 1330 if (info != null) { 1331 // process the information just read 1332 trainInfoToDialog(info); 1333 } 1334 } catch (java.io.IOException ioe) { 1335 log.error("IO Exception when reading train info file", ioe); 1336 } catch (org.jdom2.JDOMException jde) { 1337 log.error("JDOM Exception when reading train info file", jde); 1338 } 1339 } 1340 handleDelayStartClick(null); 1341 handleReverseAtEndBoxClick(null); 1342 } 1343 1344 private void saveTrainInfo(ActionEvent e, boolean locoOptional) { 1345 TrainInfo info = null; 1346 try { 1347 info = dialogToTrainInfo(locoOptional); 1348 } catch (IllegalArgumentException ide) { 1349 JmriJOptionPane.showMessageDialog(initiateFrame, ide.getMessage(), 1350 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1351 return; 1352 } 1353 // get file name 1354 String eName = ""; 1355 eName = JmriJOptionPane.showInputDialog(initiateFrame, 1356 Bundle.getMessage("EnterFileName") + " :", _trainInfoName); 1357 if (eName == null) { //Cancel pressed 1358 return; 1359 } 1360 if (eName.length() < 1) { 1361 JmriJOptionPane.showMessageDialog(initiateFrame, Bundle.getMessage("Error25"), 1362 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1363 return; 1364 } 1365 String fileName = normalizeXmlFileName(eName); 1366 _trainInfoName = fileName; 1367 // check if train info file name is in use 1368 String[] names = _tiFile.getTrainInfoFileNames(); 1369 if (names.length > 0) { 1370 boolean found = false; 1371 for (int i = 0; i < names.length; i++) { 1372 if (fileName.equals(names[i])) { 1373 found = true; 1374 } 1375 } 1376 if (found) { 1377 // file by that name is already present 1378 int selectedValue = JmriJOptionPane.showOptionDialog(initiateFrame, 1379 Bundle.getMessage("Question3", fileName), 1380 Bundle.getMessage("WarningTitle"), JmriJOptionPane.DEFAULT_OPTION, 1381 JmriJOptionPane.QUESTION_MESSAGE, null, 1382 new Object[]{Bundle.getMessage("ButtonReplace"),Bundle.getMessage("ButtonNo")}, 1383 Bundle.getMessage("ButtonNo")); 1384 if (selectedValue != 0 ) { // array position 0 , replace not selected 1385 return; // return without writing if "No" response 1386 } 1387 } 1388 } 1389 // write the Train Info file 1390 try { 1391 _tiFile.writeTrainInfo(info, fileName); 1392 } //catch (org.jdom2.JDOMException jde) { 1393 // log.error("JDOM exception writing Train Info: "+jde); 1394 //} 1395 catch (java.io.IOException ioe) { 1396 log.error("IO exception writing Train Info", ioe); 1397 } 1398 } 1399 1400 private void deleteTrainInfo(ActionEvent e) { 1401 String[] names = _tiFile.getTrainInfoFileNames(); 1402 if (names.length > 0) { 1403 Object selName = JmriJOptionPane.showInputDialog(initiateFrame, 1404 Bundle.getMessage("DeleteTrainChoice"), Bundle.getMessage("DeleteTrainTitle"), 1405 JmriJOptionPane.QUESTION_MESSAGE, null, names, names[0]); 1406 if ((selName == null) || (((String) selName).equals(""))) { 1407 return; 1408 } 1409 _tiFile.deleteTrainInfoFile((String) selName); 1410 } 1411 } 1412 1413 private void trainInfoToDialog(TrainInfo info) { 1414 try { 1415 transitSelectBox.setSelectedItemByName(info.getTransitName()); 1416 } catch (Exception ex) { 1417 log.warn("Transit {} from file not in Transit menu", info.getTransitName()); 1418 JmriJOptionPane.showMessageDialog(initiateFrame, 1419 Bundle.getMessage("TransitWarn", info.getTransitName()), 1420 null, JmriJOptionPane.WARNING_MESSAGE); 1421 } 1422 _TrainsFrom = info.getTrainsFrom(); 1423 switch (_TrainsFrom) { 1424 case TRAINSFROMROSTER: 1425 radioTrainsFromRoster.setSelected(true); 1426 if (!setRosterComboBox(rosterComboBox, info.getRosterId())) { 1427 log.warn("Roster {} from file not in Roster Combo", info.getRosterId()); 1428 JmriJOptionPane.showMessageDialog(initiateFrame, 1429 Bundle.getMessage("TrainWarn", info.getRosterId()), 1430 null, JmriJOptionPane.WARNING_MESSAGE); 1431 } 1432 break; 1433 case TRAINSFROMOPS: 1434 radioTrainsFromOps.setSelected(true); 1435 if (!setTrainComboBox(trainSelectBox, info.getTrainName())) { 1436 log.warn("Train {} from file not in Train Combo", info.getTrainName()); 1437 JmriJOptionPane.showMessageDialog(initiateFrame, 1438 Bundle.getMessage("TrainWarn", info.getTrainName()), 1439 null, JmriJOptionPane.WARNING_MESSAGE); 1440 } 1441 break; 1442 case TRAINSFROMUSER: 1443 radioTrainsFromUser.setSelected(true); 1444 dccAddressSpinner.setValue(Integer.parseInt(info.getDccAddress())); 1445 break; 1446 case TRAINSFROMSETLATER: 1447 default: 1448 radioTrainsFromSetLater.setSelected(true); 1449 } 1450 trainNameField.setText(info.getTrainUserName()); 1451 trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection()); 1452 inTransitBox.setSelected(info.getTrainInTransit()); 1453 initializeStartingBlockCombo(); 1454 initializeDestinationBlockCombo(); 1455 setComboBox(startingBlockBox, info.getStartBlockName()); 1456 setComboBox(destinationBlockBox, info.getDestinationBlockName()); 1457 prioritySpinner.setValue(info.getPriority()); 1458 resetWhenDoneBox.setSelected(info.getResetWhenDone()); 1459 reverseAtEndBox.setSelected(info.getReverseAtEnd()); 1460 setDelayModeBox(info.getDelayedStart(), delayedStartBox); 1461 //delayedStartBox.setSelected(info.getDelayedStart()); 1462 departureHrSpinner.setValue(info.getDepartureTimeHr()); 1463 departureMinSpinner.setValue(info.getDepartureTimeMin()); 1464 delaySensor.setSelectedItem(info.getDelaySensor()); 1465 resetStartSensorBox.setSelected(info.getResetStartSensor()); 1466 setDelayModeBox(info.getDelayedRestart(), delayedReStartBox); 1467 delayMinSpinner.setValue(info.getRestartDelayMin()); 1468 delayReStartSensor.setSelectedItem(info.getRestartSensor()); 1469 resetRestartSensorBox.setSelected(info.getResetRestartSensor()); 1470 1471 resetStartSensorBox.setSelected(info.getResetStartSensor()); 1472 setDelayModeBox(info.getReverseDelayedRestart(), reverseDelayedRestartType); 1473 delayReverseMinSpinner.setValue(info.getReverseRestartDelayMin()); 1474 delayReverseReStartSensor.setSelectedItem(info.getReverseRestartSensor()); 1475 delayReverseResetSensorBox.setSelected(info.getReverseResetRestartSensor()); 1476 1477 terminateWhenDoneBox.setSelected(info.getTerminateWhenDone()); 1478 nextTrain.setSelectedIndex(-1); 1479 1480 try { 1481 nextTrain.setSelectedItem(info.getNextTrain()); 1482 } catch (Exception ex){ 1483 nextTrain.setSelectedIndex(-1); 1484 } 1485 handleTerminateWhenDoneBoxClick(null); 1486 setComboBox(trainTypeBox, info.getTrainType()); 1487 autoRunBox.setSelected(info.getAutoRun()); 1488 loadAtStartupBox.setSelected(info.getLoadAtStartup()); 1489 setAllocateMethodButtons(info.getAllocationMethod()); 1490 autoTrainInfoToDialog(info); 1491 } 1492 1493 private TrainInfo dialogToTrainInfo(boolean locoOptional) throws IllegalArgumentException { 1494 TrainInfo info = new TrainInfo(); 1495 int index = transitSelectBox.getSelectedIndex(); 1496 if (index < 0) { 1497 throw new IllegalArgumentException(Bundle.getMessage("Error44")); 1498 } else { 1499 info.setTransitName(transitSelectBox.getSelectedItem().getDisplayName()); 1500 info.setTransitId(transitSelectBox.getSelectedItem().getDisplayName()); 1501 } 1502 switch (_TrainsFrom) { 1503 case TRAINSFROMROSTER: 1504 if (rosterComboBox.getSelectedIndex() < 1 ) { 1505 throw new IllegalArgumentException(Bundle.getMessage("Error41")); 1506 } 1507 info.setRosterId(((RosterEntry) rosterComboBox.getSelectedItem()).getId()); 1508 info.setDccAddress(((RosterEntry) rosterComboBox.getSelectedItem()).getDccAddress()); 1509 break; 1510 case TRAINSFROMOPS: 1511 if (trainSelectBox.getSelectedIndex() < 1) { 1512 throw new IllegalArgumentException(Bundle.getMessage("Error42")); 1513 } 1514 info.setTrainName(((Train) trainSelectBox.getSelectedItem()).getId()); 1515 info.setDccAddress(String.valueOf(dccAddressSpinner.getValue())); 1516 break; 1517 case TRAINSFROMUSER: 1518 if (trainNameField.getText().isEmpty()) { 1519 throw new IllegalArgumentException(Bundle.getMessage("Error22")); 1520 } 1521 info.setDccAddress(String.valueOf(dccAddressSpinner.getValue())); 1522 break; 1523 case TRAINSFROMSETLATER: 1524 default: 1525 info.setTrainName(""); 1526 info.setDccAddress(""); 1527 } 1528 info.setTrainUserName(trainNameField.getText()); 1529 info.setTrainInTransit(inTransitBox.isSelected()); 1530 info.setStartBlockName((String) startingBlockBox.getSelectedItem()); 1531 index = startingBlockBox.getSelectedIndex(); 1532 if (index < 0) { 1533 throw new IllegalArgumentException(Bundle.getMessage("Error13")); 1534 } else { 1535 info.setStartBlockId(startingBlockBoxList.get(index).getDisplayName()); 1536 info.setStartBlockSeq(startingBlockSeqList.get(index).intValue()); 1537 } 1538 info.setDestinationBlockName((String) destinationBlockBox.getSelectedItem()); 1539 index = destinationBlockBox.getSelectedIndex(); 1540 if (index < 0) { 1541 throw new IllegalArgumentException(Bundle.getMessage("Error8")); 1542 } else { 1543 info.setDestinationBlockId(destinationBlockBoxList.get(index).getDisplayName()); 1544 info.setDestinationBlockSeq(destinationBlockSeqList.get(index).intValue()); 1545 } 1546 info.setTrainsFrom(_TrainsFrom); 1547 info.setPriority((Integer) prioritySpinner.getValue()); 1548 info.setTrainDetection(((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value); 1549 info.setResetWhenDone(resetWhenDoneBox.isSelected()); 1550 info.setReverseAtEnd(reverseAtEndBox.isSelected()); 1551 info.setDelayedStart(delayModeFromBox(delayedStartBox)); 1552 info.setDelaySensorName(delaySensor.getSelectedItemDisplayName()); 1553 info.setResetStartSensor(resetStartSensorBox.isSelected()); 1554 info.setDepartureTimeHr((Integer) departureHrSpinner.getValue()); 1555 info.setDepartureTimeMin((Integer) departureMinSpinner.getValue()); 1556 info.setTrainType((String) trainTypeBox.getSelectedItem()); 1557 info.setAutoRun(autoRunBox.isSelected()); 1558 info.setLoadAtStartup(loadAtStartupBox.isSelected()); 1559 info.setAllocateAllTheWay(false); // force to false next field is now used. 1560 if (allocateAllTheWayRadioButton.isSelected()) { 1561 info.setAllocationMethod(ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN); 1562 } else if (allocateBySafeRadioButton.isSelected()) { 1563 info.setAllocationMethod(ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS); 1564 } else { 1565 info.setAllocationMethod((Integer) allocateCustomSpinner.getValue()); 1566 } 1567 info.setDelayedRestart(delayModeFromBox(delayedReStartBox)); 1568 info.setRestartSensorName(delayReStartSensor.getSelectedItemDisplayName()); 1569 info.setResetRestartSensor(resetRestartSensorBox.isSelected()); 1570 info.setRestartDelayMin((Integer) delayMinSpinner.getValue()); 1571 1572 info.setReverseDelayedRestart(delayModeFromBox(reverseDelayedRestartType)); 1573 info.setReverseRestartSensorName(delayReverseReStartSensor.getSelectedItemDisplayName()); 1574 info.setReverseResetRestartSensor(delayReverseResetSensorBox.isSelected()); 1575 info.setReverseRestartDelayMin((Integer) delayReverseMinSpinner.getValue()); 1576 1577 info.setTerminateWhenDone(terminateWhenDoneBox.isSelected()); 1578 if (nextTrain.getSelectedIndex() > 0 ) { 1579 info.setNextTrain((String)nextTrain.getSelectedItem()); 1580 } else { 1581 info.setNextTrain("None"); 1582 } 1583 autoRunItemsToTrainInfo(info); 1584 return info; 1585 } 1586 1587 private boolean setRosterComboBox(RosterEntryComboBox box, String txt) { 1588 boolean found = false; 1589 for (int i = 1; i < box.getItemCount(); i++) { 1590 if (txt.equals(((RosterEntry) box.getItemAt(i)).getId())) { 1591 box.setSelectedIndex(i); 1592 found = true; 1593 break; 1594 } 1595 } 1596 if (!found && box.getItemCount() > 0) { 1597 box.setSelectedIndex(0); 1598 } 1599 return found; 1600 } 1601 1602 // Normalizes a suggested xml file name. Returns null string if a valid name cannot be assembled 1603 private String normalizeXmlFileName(String name) { 1604 if (name.length() < 1) { 1605 return ""; 1606 } 1607 String newName = name; 1608 // strip off .xml or .XML if present 1609 if ((name.endsWith(".xml")) || (name.endsWith(".XML"))) { 1610 newName = name.substring(0, name.length() - 4); 1611 if (newName.length() < 1) { 1612 return ""; 1613 } 1614 } 1615 // replace all non-alphanumeric characters with underscore 1616 newName = newName.replaceAll("[\\W]", "_"); 1617 return (newName + ".xml"); 1618 } 1619 1620 private boolean setTrainComboBox(JComboBox<Object> box, String txt) { 1621 boolean found = false; 1622 for (int i = 1; i < box.getItemCount(); i++) { //skip the select train item 1623 if (txt.equals(box.getItemAt(i).toString())) { 1624 box.setSelectedIndex(i); 1625 found = true; 1626 break; 1627 } 1628 } 1629 if (!found && box.getItemCount() > 0) { 1630 box.setSelectedIndex(0); 1631 } 1632 return found; 1633 } 1634 1635 private boolean setComboBox(JComboBox<String> box, String txt) { 1636 boolean found = false; 1637 for (int i = 0; i < box.getItemCount(); i++) { 1638 if (txt.equals(box.getItemAt(i))) { 1639 box.setSelectedIndex(i); 1640 found = true; 1641 break; 1642 } 1643 } 1644 if (!found && box.getItemCount() > 0) { 1645 box.setSelectedIndex(0); 1646 } 1647 return found; 1648 } 1649 1650 int delayModeFromBox(JComboBox<String> box) { 1651 String mode = (String) box.getSelectedItem(); 1652 int result = jmri.util.StringUtil.getStateFromName(mode, delayedStartInt, delayedStartString); 1653 1654 if (result < 0) { 1655 log.warn("unexpected mode string in turnoutMode: {}", mode); 1656 throw new IllegalArgumentException(); 1657 } 1658 return result; 1659 } 1660 1661 void setDelayModeBox(int mode, JComboBox<String> box) { 1662 String result = jmri.util.StringUtil.getNameFromState(mode, delayedStartInt, delayedStartString); 1663 box.setSelectedItem(result); 1664 } 1665 1666 /** 1667 * The following are for items that are only for automatic running of 1668 * ActiveTrains They are isolated here to simplify changing them in the 1669 * future. 1670 * <ul> 1671 * <li>initializeAutoRunItems - initializes the display of auto run items in 1672 * this window 1673 * <li>initializeAutoRunValues - initializes the values of auto run items 1674 * from values in a saved train info file hideAutoRunItems - hides all auto 1675 * run items in this window showAutoRunItems - shows all auto run items in 1676 * this window 1677 * <li>autoTrainInfoToDialog - gets auto run items from a train info, puts 1678 * values in items, and initializes auto run dialog items 1679 * <li>autoTrainItemsToTrainInfo - copies values of auto run items to train 1680 * info for saving to a file 1681 * <li>readAutoRunItems - reads and checks values of all auto run items. 1682 * returns true if OK, sends appropriate messages and returns false if not 1683 * OK 1684 * <li>setAutoRunItems - sets the user entered auto run items in the new 1685 * AutoActiveTrain 1686 * </ul> 1687 */ 1688 // auto run items in ActivateTrainFrame 1689 private final JPanel pa1 = new JPanel(); 1690 private final JLabel speedFactorLabel = new JLabel(Bundle.getMessage("SpeedFactorLabel")); 1691 private final JSpinner speedFactorSpinner = new JSpinner(); 1692 private final JLabel maxSpeedLabel = new JLabel(Bundle.getMessage("MaxSpeedLabel")); 1693 private final JSpinner maxSpeedSpinner = new JSpinner(); 1694 private final JPanel pa2 = new JPanel(); 1695 private final JLabel rampRateLabel = new JLabel(Bundle.getMessage("RampRateBoxLabel")); 1696 private final JComboBox<String> rampRateBox = new JComboBox<>(); 1697 private final JPanel pa2a = new JPanel(); 1698 private final JLabel useSpeedProfileLabel = new JLabel(Bundle.getMessage("UseSpeedProfileLabel")); 1699 private final JCheckBox useSpeedProfileCheckBox = new JCheckBox( ); 1700 private final JLabel stopBySpeedProfileLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileLabel")); 1701 private final JCheckBox stopBySpeedProfileCheckBox = new JCheckBox( ); 1702 private final JLabel stopBySpeedProfileAdjustLabel = new JLabel(Bundle.getMessage("StopBySpeedProfileAdjustLabel")); 1703 private final JSpinner stopBySpeedProfileAdjustSpinner = new JSpinner(); 1704 private final JPanel pa3 = new JPanel(); 1705 private final JCheckBox soundDecoderBox = new JCheckBox(Bundle.getMessage("SoundDecoder")); 1706 private final JCheckBox runInReverseBox = new JCheckBox(Bundle.getMessage("RunInReverse")); 1707 private final JPanel pa4 = new JPanel(); 1708 protected static class TrainDetectionJCombo extends JComboBox<TrainDetectionItem> { 1709 public void setSelectedItemByValue(TrainDetection var) { 1710 for ( int ix = 0; ix < getItemCount() ; ix ++ ) { 1711 if (getItemAt(ix).value == var) { 1712 this.setSelectedIndex(ix); 1713 break; 1714 } 1715 } 1716 } 1717 } 1718 public final TrainDetectionJCombo trainDetectionComboBox 1719 = new TrainDetectionJCombo(); 1720 private final JLabel trainDetectionLabel = new JLabel(Bundle.getMessage("TrainDetection")); 1721 private final JLabel trainLengthLabel = new JLabel(Bundle.getMessage("MaxTrainLengthLabel")); 1722 private final JSpinner maxTrainLengthSpinner = new JSpinner(); // initialized later 1723 // auto run variables 1724 float _speedFactor = 1.0f; 1725 float _maxSpeed = 0.6f; 1726 int _rampRate = AutoActiveTrain.RAMP_NONE; 1727 TrainDetection _trainDetection = TrainDetection.TRAINDETECTION_HEADONLY; 1728 boolean _runInReverse = false; 1729 boolean _soundDecoder = false; 1730 float _maxTrainLength = 200.0f; 1731 boolean _stopBySpeedProfile = false; 1732 float _stopBySpeedProfileAdjust = 1.0f; 1733 boolean _useSpeedProfile = true; 1734 String _nextTrain = ""; 1735 1736 private void setAutoRunDefaults() { 1737 _speedFactor = 1.0f; 1738 _maxSpeed = 0.6f; 1739 _rampRate = AutoActiveTrain.RAMP_NONE; 1740 _runInReverse = false; 1741 _soundDecoder = false; 1742 _maxTrainLength = 100.0f; 1743 _stopBySpeedProfile = false; 1744 _stopBySpeedProfileAdjust = 1.0f; 1745 _useSpeedProfile = true; 1746 _nextTrain = ""; 1747 1748 } 1749 1750 private void initializeAutoRunItems() { 1751 initializeRampCombo(); 1752 pa1.setLayout(new FlowLayout()); 1753 pa1.add(speedFactorLabel); 1754 speedFactorSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(2.0f), Float.valueOf(0.01f))); 1755 speedFactorSpinner.setEditor(new JSpinner.NumberEditor(speedFactorSpinner, "# %")); 1756 pa1.add(speedFactorSpinner); 1757 speedFactorSpinner.setToolTipText(Bundle.getMessage("SpeedFactorHint")); 1758 pa1.add(new JLabel(" ")); 1759 pa1.add(maxSpeedLabel); 1760 maxSpeedSpinner.setModel(new SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(2.0f), Float.valueOf(0.01f))); 1761 maxSpeedSpinner.setEditor(new JSpinner.NumberEditor(maxSpeedSpinner, "# %")); 1762 pa1.add(maxSpeedSpinner); 1763 maxSpeedSpinner.setToolTipText(Bundle.getMessage("MaxSpeedHint")); 1764 initiatePane.add(pa1); 1765 pa2.setLayout(new FlowLayout()); 1766 pa2.add(rampRateLabel); 1767 pa2.add(rampRateBox); 1768 rampRateBox.setToolTipText(Bundle.getMessage("RampRateBoxHint")); 1769 pa2.add(useSpeedProfileLabel); 1770 pa2.add(useSpeedProfileCheckBox); 1771 useSpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint")); 1772 initiatePane.add(pa2); 1773 pa2a.setLayout(new FlowLayout()); 1774 pa2a.add(stopBySpeedProfileLabel); 1775 pa2a.add(stopBySpeedProfileCheckBox); 1776 stopBySpeedProfileCheckBox.setToolTipText(Bundle.getMessage("UseSpeedProfileHint")); // reuse identical hint for Stop 1777 pa2a.add(stopBySpeedProfileAdjustLabel); 1778 stopBySpeedProfileAdjustSpinner.setModel(new SpinnerNumberModel( Float.valueOf(1.0f), Float.valueOf(0.1f), Float.valueOf(5.0f), Float.valueOf(0.01f))); 1779 stopBySpeedProfileAdjustSpinner.setEditor(new JSpinner.NumberEditor(stopBySpeedProfileAdjustSpinner, "# %")); 1780 pa2a.add(stopBySpeedProfileAdjustSpinner); 1781 stopBySpeedProfileAdjustSpinner.setToolTipText(Bundle.getMessage("StopBySpeedProfileAdjustHint")); 1782 initiatePane.add(pa2a); 1783 pa3.setLayout(new FlowLayout()); 1784 pa3.add(soundDecoderBox); 1785 soundDecoderBox.setToolTipText(Bundle.getMessage("SoundDecoderBoxHint")); 1786 pa3.add(new JLabel(" ")); 1787 pa3.add(runInReverseBox); 1788 runInReverseBox.setToolTipText(Bundle.getMessage("RunInReverseBoxHint")); 1789 initiatePane.add(pa3); 1790 pa4.setLayout(new FlowLayout()); 1791 pa4.add(trainLengthLabel); 1792 maxTrainLengthSpinner.setModel(new SpinnerNumberModel(Float.valueOf(18.0f), Float.valueOf(0.0f), Float.valueOf(10000.0f), Float.valueOf(0.5f))); 1793 maxTrainLengthSpinner.setEditor(new JSpinner.NumberEditor(maxTrainLengthSpinner, "###0.0")); 1794 pa4.add(maxTrainLengthSpinner); 1795 boolean unitIsMeter = InstanceManager.getDefault(DispatcherFrame.class).getUseScaleMeters(); // read from user setting 1796 maxTrainLengthSpinner.setToolTipText(Bundle.getMessage("MaxTrainLengthHint", 1797 (unitIsMeter ? Bundle.getMessage("ScaleMeters") : Bundle.getMessage("ScaleFeet")))); // won't be updated while Dispatcher is open 1798 initiatePane.add(pa4); 1799 hideAutoRunItems(); // initialize with auto run items hidden 1800 initializeAutoRunValues(); 1801 } 1802 1803 private void initializeAutoRunValues() { 1804 speedFactorSpinner.setValue(_speedFactor); 1805 maxSpeedSpinner.setValue(_maxSpeed); 1806 rampRateBox.setSelectedIndex(_rampRate); 1807 soundDecoderBox.setSelected(_soundDecoder); 1808 runInReverseBox.setSelected(_runInReverse); 1809 useSpeedProfileCheckBox.setSelected(_useSpeedProfile); 1810 stopBySpeedProfileAdjustSpinner.setValue(_stopBySpeedProfileAdjust); 1811 stopBySpeedProfileCheckBox.setSelected(_stopBySpeedProfile); 1812 maxTrainLengthSpinner.setValue(Math.round(_maxTrainLength * 2) * 0.5f); // set in spinner as 0.5 increments 1813 1814 } 1815 1816 private void hideAutoRunItems() { 1817 pa1.setVisible(false); 1818 pa2.setVisible(false); 1819 pa2a.setVisible(false); 1820 pa3.setVisible(false); 1821 pa4.setVisible(false); 1822 } 1823 1824 private void showAutoRunItems() { 1825 pa1.setVisible(true); 1826 pa2.setVisible(true); 1827 pa2a.setVisible(true); 1828 pa3.setVisible(true); 1829 pa4.setVisible(true); 1830 } 1831 1832 private void autoTrainInfoToDialog(TrainInfo info) { 1833 speedFactorSpinner.setValue(info.getSpeedFactor()); 1834 maxSpeedSpinner.setValue(info.getMaxSpeed()); 1835 setComboBox(rampRateBox, info.getRampRate()); 1836 trainDetectionComboBox.setSelectedItemByValue(info.getTrainDetection()); 1837 runInReverseBox.setSelected(info.getRunInReverse()); 1838 soundDecoderBox.setSelected(info.getSoundDecoder()); 1839 maxTrainLengthSpinner.setValue(info.getMaxTrainLength()); 1840 useSpeedProfileCheckBox.setSelected(info.getUseSpeedProfile()); 1841 stopBySpeedProfileCheckBox.setSelected(info.getStopBySpeedProfile()); 1842 stopBySpeedProfileAdjustSpinner.setValue(info.getStopBySpeedProfileAdjust()); 1843 if (autoRunBox.isSelected()) { 1844 showAutoRunItems(); 1845 } else { 1846 hideAutoRunItems(); 1847 } 1848 initiateFrame.pack(); 1849 } 1850 1851 private void autoRunItemsToTrainInfo(TrainInfo info) { 1852 info.setSpeedFactor((float) speedFactorSpinner.getValue()); 1853 info.setMaxSpeed((float) maxSpeedSpinner.getValue()); 1854 info.setRampRate((String) rampRateBox.getSelectedItem()); 1855 info.setRunInReverse(runInReverseBox.isSelected()); 1856 info.setSoundDecoder(soundDecoderBox.isSelected()); 1857 info.setMaxTrainLength((float) maxTrainLengthSpinner.getValue()); 1858 // Only use speed profile values if enabled 1859 if (useSpeedProfileCheckBox.isEnabled()) { 1860 info.setUseSpeedProfile(useSpeedProfileCheckBox.isSelected()); 1861 info.setStopBySpeedProfile(stopBySpeedProfileCheckBox.isSelected()); 1862 info.setStopBySpeedProfileAdjust((float) stopBySpeedProfileAdjustSpinner.getValue()); 1863 } else { 1864 info.setUseSpeedProfile(false); 1865 info.setStopBySpeedProfile(false); 1866 info.setStopBySpeedProfileAdjust(1.0f); 1867 } 1868 } 1869 1870 private boolean readAutoRunItems() { 1871 boolean success = true; 1872 _speedFactor = (float) speedFactorSpinner.getValue(); 1873 _maxSpeed = (float) maxSpeedSpinner.getValue(); 1874 _rampRate = rampRateBox.getSelectedIndex(); 1875 _trainDetection = ((TrainDetectionItem)trainDetectionComboBox.getSelectedItem()).value; 1876 _runInReverse = runInReverseBox.isSelected(); 1877 _soundDecoder = soundDecoderBox.isSelected(); 1878 _maxTrainLength = (float) maxTrainLengthSpinner.getValue(); 1879 _useSpeedProfile = useSpeedProfileCheckBox.isSelected(); 1880 _stopBySpeedProfile = stopBySpeedProfileCheckBox.isSelected(); 1881 if (_stopBySpeedProfile) { 1882 _stopBySpeedProfileAdjust = (Float) stopBySpeedProfileAdjustSpinner.getValue(); 1883 } 1884 if (nextTrain.getSelectedIndex() < 0) { 1885 _nextTrain=""; 1886 } else { 1887 _nextTrain = (String)nextTrain.getSelectedItem(); 1888 } 1889 return success; 1890 } 1891 1892 private void setAutoRunItems(AutoActiveTrain aaf) { 1893 aaf.setSpeedFactor(_speedFactor); 1894 aaf.setMaxSpeed(_maxSpeed); 1895 aaf.setRampRate(_rampRate); 1896 aaf.setRunInReverse(_runInReverse); 1897 aaf.setSoundDecoder(_soundDecoder); 1898 aaf.setMaxTrainLength(_maxTrainLength); 1899 aaf.setStopBySpeedProfile(_stopBySpeedProfile); 1900 aaf.setStopBySpeedProfileAdjust(_stopBySpeedProfileAdjust); 1901 aaf.setUseSpeedProfile(_useSpeedProfile); 1902 } 1903 1904 private void initializeRampCombo() { 1905 rampRateBox.removeAllItems(); 1906 rampRateBox.addItem(Bundle.getMessage("RAMP_NONE")); 1907 rampRateBox.addItem(Bundle.getMessage("RAMP_FAST")); 1908 rampRateBox.addItem(Bundle.getMessage("RAMP_MEDIUM")); 1909 rampRateBox.addItem(Bundle.getMessage("RAMP_MED_SLOW")); 1910 rampRateBox.addItem(Bundle.getMessage("RAMP_SLOW")); 1911 rampRateBox.addItem(Bundle.getMessage("RAMP_SPEEDPROFILE")); 1912 // Note: the order above must correspond to the numbers in AutoActiveTrain.java 1913 } 1914 1915 /** 1916 * Sets up the RadioButtons and visability of spinner for the allocation method 1917 * 1918 * @param value 0, Allocate by Safe spots, -1, allocate as far as possible Any 1919 * other value the number of sections to allocate 1920 */ 1921 private void setAllocateMethodButtons(int value) { 1922 switch (value) { 1923 case ActiveTrain.ALLOCATE_BY_SAFE_SECTIONS: 1924 allocateBySafeRadioButton.setSelected(true); 1925 allocateCustomSpinner.setVisible(false); 1926 break; 1927 case ActiveTrain.ALLOCATE_AS_FAR_AS_IT_CAN: 1928 allocateAllTheWayRadioButton.setSelected(true); 1929 allocateCustomSpinner.setVisible(false); 1930 break; 1931 default: 1932 allocateNumberOfBlocks.setSelected(true); 1933 allocateCustomSpinner.setVisible(true); 1934 allocateCustomSpinner.setValue(value); 1935 } 1936 } 1937 1938 /* 1939 * ComboBox item. 1940 */ 1941 protected static class TrainDetectionItem { 1942 private String key; 1943 private TrainDetection value; 1944 public TrainDetectionItem(String text, TrainDetection trainDetection ) { 1945 this.key = text; 1946 this.value = trainDetection; 1947 } 1948 @Override 1949 public String toString() 1950 { 1951 return key; 1952 } 1953 public String getKey() 1954 { 1955 return key; 1956 } 1957 public TrainDetection getValue() 1958 { 1959 return value; 1960 } 1961 } 1962 1963 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActivateTrainFrame.class); 1964 1965}