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