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