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