001package jmri.jmrit.dispatcher; 002 003import java.awt.BorderLayout; 004import java.awt.Dimension; 005import java.awt.FlowLayout; 006import java.awt.event.ActionEvent; 007import java.util.ArrayList; 008 009import javax.swing.BoxLayout; 010import javax.swing.ButtonGroup; 011import javax.swing.JButton; 012import javax.swing.JCheckBoxMenuItem; 013import javax.swing.JLabel; 014import javax.swing.JMenu; 015import javax.swing.JMenuBar; 016import javax.swing.JPanel; 017import javax.swing.JRadioButton; 018import javax.swing.JScrollPane; 019import javax.swing.JSeparator; 020import javax.swing.JSlider; 021import javax.swing.JTextField; 022 023import java.beans.PropertyChangeEvent; 024 025import javax.swing.JToolBar; 026import javax.swing.event.AncestorEvent; 027import javax.swing.event.AncestorListener; 028import javax.swing.plaf.basic.BasicToolBarUI; 029 030import jmri.Block; 031import jmri.Throttle; 032import jmri.jmrit.roster.RosterEntry; 033import jmri.util.JmriJFrame; 034import jmri.util.swing.JmriJOptionPane; 035 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039/** 040 * AutoTrainsFrame provides a user interface to trains that are running 041 * automatically under Dispatcher. 042 * <p> 043 * There is only one AutoTrains window. AutoTrains are added and deleted from 044 * this window as they are added or terminated. 045 * <p> 046 * This file is part of JMRI. 047 * <p> 048 * JMRI is open source software; you can redistribute it and/or modify it under 049 * the terms of version 2 of the GNU General Public License as published by the 050 * Free Software Foundation. See the "COPYING" file for a copy of this license. 051 * <p> 052 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 053 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 054 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 055 * 056 * @author Dave Duchamp Copyright (C) 2010 057 */ 058public class AutoTrainsFrame extends jmri.util.JmriJFrame { 059 060 public AutoTrainsFrame(DispatcherFrame disp) { 061 super(false, true); 062 initializeAutoTrainsWindow(); 063 } 064 065 // instance variables 066 private final ArrayList<AutoActiveTrain> _autoTrainsList = new ArrayList<>(); 067 //Keep track of throttle and listeners to update frame with their current state. 068 069 // accessor functions 070 public ArrayList<AutoActiveTrain> getAutoTrainsList() { 071 return _autoTrainsList; 072 } 073 074 /** 075 * Creates and initializes a new control of type AutoTrainControl 076 * @param autoActiveTrain the new train. 077 */ 078 public void addAutoActiveTrain(AutoActiveTrain autoActiveTrain) { 079 if (autoActiveTrain != null) { 080 log.debug("Adding ActiveTrain[{}]",autoActiveTrain.getActiveTrain().getActiveTrainName()); 081 AutoTrainControl atn = new AutoTrainControl(autoActiveTrain); 082 if (!trainsCanBeFloated.isSelected()) { 083 atn.componentJPanel.setFloatable(false); 084 } 085 trainsPanel.add(atn); 086 atn.addPropertyChangeListener("terminated", (PropertyChangeEvent e) -> { 087 AutoTrainControl atnn = (AutoTrainControl) e.getSource(); 088 // must be attached to make it really go away 089 ((BasicToolBarUI) atnn.componentJPanel.getUI()).setFloating(false,null); 090 trainsPanel.remove((AutoTrainControl) e.getSource()); 091 pack(); 092 }); 093 // bit of overkill for when a floater floats and comes back. 094 atn.componentJPanel.addAncestorListener ( new AncestorListener () 095 { 096 @Override 097 public void ancestorAdded ( AncestorEvent event ) 098 { 099 log.trace("ancestorAdded"); 100 pack(); 101 } 102 @Override 103 public void ancestorRemoved ( AncestorEvent event ) 104 { 105 log.trace("ancestorRemoved"); 106 pack(); 107 } 108 @Override 109 public void ancestorMoved ( AncestorEvent event ) 110 { 111 // blank. 112 } 113 } ); 114 pack(); 115 } 116 } 117 118 // variables for AutoTrains window 119 protected JmriJFrame autoTrainsFrame = null; 120 private JPanel trainsPanel; 121 private JScrollPane trainScrollPanel; 122 private JCheckBoxMenuItem frameHasScrollBars = new JCheckBoxMenuItem(Bundle.getMessage("AutoTrainsFrameUseScrollBars")); 123 private JCheckBoxMenuItem trainsCanBeFloated = new JCheckBoxMenuItem(Bundle.getMessage("AutoTrainsFrameAllowFloat")); 124 private JCheckBoxMenuItem frameAlwaysOnTop = new JCheckBoxMenuItem(Bundle.getMessage("AutoTrainsFrameAlwaysOnTop")); 125 private JCheckBoxMenuItem frameOnTopOnSpeedChange = new JCheckBoxMenuItem(Bundle.getMessage("AutoTrainsFrameOnTopOnSpeedChange")); 126 127 jmri.UserPreferencesManager prefMan; 128 129 private void initializeAutoTrainsWindow() { 130 131 prefMan = jmri.InstanceManager.getDefault(jmri.UserPreferencesManager.class); 132 frameHasScrollBars.setSelected(prefMan.getSimplePreferenceState(hasScrollBars)); 133 trainsCanBeFloated.setSelected(prefMan.getSimplePreferenceState(canFloat)); 134 frameAlwaysOnTop.setSelected(prefMan.getSimplePreferenceState(alWaysOnTop)); 135 frameOnTopOnSpeedChange.setSelected(prefMan.getSimplePreferenceState(onTopOnSpeedChange)); 136 137 138 autoTrainsFrame = this; 139 autoTrainsFrame.setTitle(Bundle.getMessage("TitleAutoTrains")); 140 trainsPanel = new JPanel(); 141 trainsPanel.setLayout(new BoxLayout(trainsPanel, BoxLayout.Y_AXIS)); 142 JMenuBar menuBar = new JMenuBar(); 143 JMenu optMenu = new JMenu(Bundle.getMessage("MenuOptions")); // NOI18N 144 optMenu.add(frameHasScrollBars); 145 frameHasScrollBars.addActionListener(e -> { 146 setScrollBars(); 147 }); 148 149 optMenu.add(trainsCanBeFloated); 150 trainsCanBeFloated.addActionListener(e -> { 151 for (Object ob : trainsPanel.getComponents()) { 152 if (ob instanceof AutoTrainControl) { 153 AutoTrainControl atnn = (AutoTrainControl) ob; 154 if (trainsCanBeFloated.isSelected()) { 155 atnn.componentJPanel.setFloatable(true); 156 } else { 157 // rejoin floating throttles before banning 158 // floating. 159 ((BasicToolBarUI) atnn.componentJPanel.getUI()).setFloating(false, null); 160 atnn.componentJPanel.setFloatable(false); 161 } 162 } 163 } 164 }); 165 166 optMenu.add(frameAlwaysOnTop); 167 frameAlwaysOnTop.addActionListener(e -> { 168 setAlwaysOnTop(frameAlwaysOnTop.isSelected()); 169 }); 170 171 optMenu.add(frameOnTopOnSpeedChange); 172 frameOnTopOnSpeedChange.addActionListener(e -> { 173 for (Object ob : trainsPanel.getComponents()) { 174 if (ob instanceof AutoTrainControl) { 175 AutoTrainControl atnn = (AutoTrainControl) ob; 176 atnn.setOnTopOnSpeedChange(frameOnTopOnSpeedChange.isSelected()); 177 } 178 } 179 }); 180 181 menuBar.add(optMenu); 182 183 setJMenuBar(menuBar); 184 autoTrainsFrame.addHelpMenu("package.jmri.jmrit.dispatcher.AutoTrains", true); 185 trainsPanel.setLayout(new BoxLayout(trainsPanel, BoxLayout.Y_AXIS)); 186 JPanel pB = new JPanel(); 187 pB.setLayout(new FlowLayout()); 188 JButton stopAllButton = new JButton(Bundle.getMessage("StopAll")); 189 pB.add(stopAllButton); 190 stopAllButton.addActionListener(this::stopAllPressed); 191 stopAllButton.setToolTipText(Bundle.getMessage("StopAllButtonHint")); 192 trainsPanel.add(pB); 193 trainsPanel.add(new JSeparator()); 194 trainsPanel.addComponentListener(this); 195 trainsPanel.setVisible(true); 196 trainsPanel.revalidate(); 197 trainScrollPanel = new JScrollPane(); 198 trainScrollPanel.getViewport().add(trainsPanel); 199 autoTrainsFrame.getContentPane().setLayout(new BoxLayout(autoTrainsFrame.getContentPane(), BoxLayout.Y_AXIS)); 200 autoTrainsFrame.getContentPane().add(trainScrollPanel); 201 setScrollBars(); 202 autoTrainsFrame.getContentPane().revalidate(); 203 autoTrainsFrame.pack(); 204 autoTrainsFrame.setVisible(true); 205 206 } 207 208 private void setScrollBars() { 209 if (frameHasScrollBars.isSelected()) { 210 trainScrollPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 211 trainScrollPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 212 autoTrainsFrame.getContentPane().revalidate(); 213 } else { 214 trainScrollPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); 215 trainScrollPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 216 autoTrainsFrame.getContentPane().revalidate(); 217 } 218 } 219 220 private void stopAllPressed(ActionEvent e) { 221 for (Object ob: trainsPanel.getComponents()) { 222 if (ob instanceof AutoTrainControl) { 223 ((AutoTrainControl) ob).stopAll(); 224 } 225 } 226 } 227 228 @Override 229 public void dispose() { 230 if (prefMan!=null) { 231 prefMan.setSimplePreferenceState(hasScrollBars, frameHasScrollBars.isSelected()); 232 prefMan.setSimplePreferenceState(canFloat, trainsCanBeFloated.isSelected()); 233 prefMan.setSimplePreferenceState(hasScrollBars, frameHasScrollBars.isSelected()); 234 prefMan.setSimplePreferenceState(canFloat, trainsCanBeFloated.isSelected()); 235 } 236 super.dispose(); 237 } 238 String hasScrollBars = this.getClass().getName() + ".HasScrollBars"; // NOI18N 239 String canFloat = this.getClass().getName() + ".CanFloat"; // NOI18N 240 String alWaysOnTop = this.getClass().getName() + ".AlWaysOnTop"; // NOI18N 241 String onTopOnSpeedChange = this.getClass().getName() + ".OnTopOnSpeedChange"; // NOI18N 242 class AutoTrainControl extends JPanel { 243 244 private boolean useOnTopOnSpeedChange; 245 246 public AutoTrainControl(AutoActiveTrain autoActiveTrain) { 247 this.autoActiveTrain = autoActiveTrain; 248 activeTrain = autoActiveTrain.getActiveTrain(); 249 activeTrain.addPropertyChangeListener(activeTrainListener = new java.beans.PropertyChangeListener() { 250 @Override 251 public void propertyChange(java.beans.PropertyChangeEvent e) { 252 handleActiveTrainListen(e); 253 } 254 }); 255 rosterEntry = autoActiveTrain.getRosterEntry(); 256 drawComponent(); 257 } 258 259 protected void setOnTopOnSpeedChange(boolean value) { 260 useOnTopOnSpeedChange = value; 261 } 262 263 protected void stopAll() { 264 if (activeTrain.getStatus() != ActiveTrain.STOPPED && 265 activeTrain.getStatus() != ActiveTrain.DONE) { 266 autoActiveTrain.saveSpeedAndDirection(); 267 autoActiveTrain.getAutoEngineer().setHalt(true); 268 autoActiveTrain.setSavedStatus(activeTrain.getStatus()); 269 activeTrain.setStatus(ActiveTrain.STOPPED); 270 } 271 } 272 273 private AutoActiveTrain autoActiveTrain = null; 274 private java.beans.PropertyChangeListener activeTrainListener = null; 275 private java.beans.PropertyChangeListener throttleListener = null; 276 private jmri.Throttle throttle = null; 277 private ActiveTrain activeTrain = null; 278 private RosterEntry rosterEntry = null; 279 280 private JLabel trainLabel; 281 private JLabel throttleStatus; 282 protected JButton stopButton; 283 private JButton resumeAutoRunningButton; 284 private JRadioButton forwardButton; 285 private JRadioButton reverseButton; 286 private JSlider speedSlider; 287 private JButton manualButton; 288 289 private void handleThrottleListen(java.beans.PropertyChangeEvent e) { 290 if (!e.getPropertyName().equals(Throttle.SPEEDSETTING) && !e.getPropertyName().equals(Throttle.ISFORWARD)) { 291 return; // ignore if not speed or direction 292 } 293 updateThrottleDisplay(e); 294 } 295 296 private float lastReportedSpeed; // for display purposes 297 298 /* 299 * Updates screen control throttle. 300 */ 301 private void primeThrottleDisplay() { 302 if (throttle != null) { 303 if (throttle.getIsForward()) { 304 forwardButton.setSelected(true); 305 } else { 306 reverseButton.setSelected(true); 307 } 308 lastReportedSpeed = throttle.getSpeedSetting(); 309 if (speedSlider.isVisible()) { 310 speedSlider.setValue(Math.round(lastReportedSpeed * 100.0f)); 311 } 312 } 313 updateThrottleStatus(); 314 } 315 316 /* 317 * Updates control from events 318 */ 319 private void updateThrottleDisplay(java.beans.PropertyChangeEvent e) { 320 if (throttle != null) { 321 if (e.getPropertyName().equals(Throttle.ISFORWARD)) { 322 if ((boolean) e.getNewValue()) { 323 forwardButton.setSelected(true); 324 } else { 325 reverseButton.setSelected(true); 326 } 327 } else { 328 lastReportedSpeed = (float) e.getNewValue(); 329 if (speedSlider.isVisible()) { 330 speedSlider.setValue(Math.round(lastReportedSpeed * 100.0f)); 331 } 332 } 333 } 334 updateThrottleStatus(); 335 } 336 337 /* 338 * Updates the status words. 339 */ 340 private void updateThrottleStatus() { 341 StringBuilder sb = new StringBuilder(); 342 if (throttle != null && throttleStatus.isVisible()) { 343 if (rosterEntry != null && autoActiveTrain.useSpeedProfile && rosterEntry.getSpeedProfile() != null) { 344 sb.append("" + 345 rosterEntry.getSpeedProfile().convertThrottleSettingToScaleSpeedWithUnits( 346 lastReportedSpeed, 347 forwardButton.isSelected())); 348 } else { 349 sb.append("" + Math.round(throttle.getSpeedSetting() * 100)); 350 sb.append("% "); 351 } 352 if (forwardButton.isSelected()) { 353 sb.append("(fwd)"); 354 } else { 355 sb.append("(rev)"); 356 } 357 throttleStatus.setText(sb.toString()); 358 if (useOnTopOnSpeedChange) { 359 // bring to front without getting focus 360 setAlwaysOnTop(true); 361 setAlwaysOnTop(false); 362 } 363 } else if (throttleStatus.isVisible()) { 364 throttleStatus.setText("No Throttle"); 365 } 366 } 367 368 private void handleActiveTrainListen(java.beans.PropertyChangeEvent e) { 369 if (e.getNewValue() != null) { 370 log.trace("Property[{}] newValue[{}]",e.getPropertyName(),e.getNewValue()); 371 } else { 372 log.trace("Property[{}] newValue[{}]",e.getPropertyName(),"NULL"); 373 } 374 if (e.getPropertyName().equals("mode")) { 375 int newValue = ((Integer) e.getNewValue()).intValue(); 376 if (newValue == ActiveTrain.DISPATCHED) { 377 stopButton.setVisible(false); 378 manualButton.setVisible(false); 379 resumeAutoRunningButton.setVisible(true); 380 forwardButton.setVisible(false); 381 reverseButton.setVisible(false); 382 speedSlider.setVisible(false); 383 throttleStatus.setVisible(false); 384 jmri.InstanceManager.throttleManagerInstance().removeListener(throttle.getLocoAddress(), 385 throttleListener); 386 } else if (newValue == ActiveTrain.AUTOMATIC) { 387 log.trace("[{}]:Set auto", autoActiveTrain.getActiveTrain().getActiveTrainName()); 388 if (throttle == null && autoActiveTrain.getThrottle() != null) { 389 log.trace("[{}]:Set new throttle", autoActiveTrain.getActiveTrain().getActiveTrainName()); 390 throttle = autoActiveTrain.getThrottle(); 391 throttleListener = new java.beans.PropertyChangeListener() { 392 @Override 393 public void propertyChange(java.beans.PropertyChangeEvent e) { 394 handleThrottleListen(e); 395 } 396 }; 397 jmri.InstanceManager.throttleManagerInstance().attachListener(throttle.getLocoAddress(), throttleListener); 398 rosterEntry = autoActiveTrain.getRosterEntry(); 399 setStatusLabelWidth(); 400 stopButton.setText(Bundle.getMessage("StopButton")); 401 stopButton.setToolTipText(Bundle.getMessage("StopButtonHint")); 402 stopButton.setVisible(true); 403 manualButton.setText(Bundle.getMessage("ToManualButton")); 404 manualButton.setToolTipText(Bundle.getMessage("ToManualButtonHint")); 405 manualButton.setVisible(true); 406 resumeAutoRunningButton.setVisible(false); 407 forwardButton.setVisible(false); 408 reverseButton.setVisible(false); 409 speedSlider.setVisible(false); 410 throttleStatus.setVisible(true); 411 primeThrottleDisplay(); 412 } 413 } else if ((int) e.getNewValue() == ActiveTrain.TERMINATED) { 414 if (throttle != null && throttleListener != null) { 415 throttle.removePropertyChangeListener(throttleListener); 416 throttle = null; 417 } 418 activeTrain.removePropertyChangeListener(activeTrainListener); 419 // please someone stop me before I do something silly 420 firePropertyChange("terminated", null, null); 421 } 422 } else if (e.getPropertyName().equals("status")) { 423 log.debug("NewStatus[{}]", e.getNewValue()); 424 if ((int) e.getNewValue() == ActiveTrain.STOPPED) { 425 stopButton.setText(Bundle.getMessage("ResumeButton")); 426 stopButton.setToolTipText(Bundle.getMessage("ResumeButtonHint")); 427 stopButton.setVisible(true); 428 } else if ((int) e.getNewValue() == ActiveTrain.RUNNING || 429 (int) e.getNewValue() == ActiveTrain.WAITING || 430 (int) e.getNewValue() == ActiveTrain.READY ) { 431 log.trace("[{}]:Set auto STATUS RUNNING", autoActiveTrain.getActiveTrain().getActiveTrainName()); 432 if (throttle == null && autoActiveTrain.getThrottle() != null) { 433 log.debug("[{}]:Set new throttle", autoActiveTrain.getActiveTrain().getActiveTrainName()); 434 throttle = autoActiveTrain.getThrottle(); 435 throttleListener = new java.beans.PropertyChangeListener() { 436 @Override 437 public void propertyChange(java.beans.PropertyChangeEvent e) { 438 handleThrottleListen(e); 439 } 440 }; 441 jmri.InstanceManager.throttleManagerInstance().attachListener(throttle.getLocoAddress(), throttleListener); 442 rosterEntry = autoActiveTrain.getRosterEntry(); 443 setStatusLabelWidth(); 444 } 445 stopButton.setText(Bundle.getMessage("StopButton")); 446 stopButton.setToolTipText(Bundle.getMessage("StopButtonHint")); 447 stopButton.setVisible(true); 448 manualButton.setText(Bundle.getMessage("ToManualButton")); 449 manualButton.setToolTipText(Bundle.getMessage("ToManualButtonHint")); 450 manualButton.setVisible(true); 451 resumeAutoRunningButton.setVisible(false); 452 forwardButton.setVisible(false); 453 reverseButton.setVisible(false); 454 speedSlider.setVisible(false); 455 throttleStatus.setVisible(true); 456 primeThrottleDisplay(); 457 } else if ((int) e.getNewValue() == ActiveTrain.DONE) { 458 stopButton.setText(Bundle.getMessage("RestartButton")); 459 stopButton.setToolTipText(Bundle.getMessage("RestartButtonHint")); 460 stopButton.setVisible(true); 461 } else { 462 log.debug("Ignored newstatus[{}]", e.getNewValue()); 463 } 464 } 465 pack(); 466 } 467 468 public void manualAutoTrain() { 469 if (activeTrain.getMode() == ActiveTrain.AUTOMATIC) { 470 activeTrain.setMode(ActiveTrain.MANUAL); 471 manualButton.setText(Bundle.getMessage("ToAutoButton")); 472 manualButton.setToolTipText(Bundle.getMessage("ToAutoButtonHint")); 473 forwardButton.setVisible(true); 474 reverseButton.setVisible(true); 475 speedSlider.setVisible(true); 476 if (autoActiveTrain.getAutoEngineer() != null) { 477 autoActiveTrain.saveSpeedAndDirection(); 478 autoActiveTrain.getAutoEngineer().setHalt(true); 479 autoActiveTrain.setTargetSpeed(0.0f); 480 autoActiveTrain.waitUntilStopped(); 481 autoActiveTrain.getAutoEngineer().setHalt(false); 482 if (throttle.getIsForward() ) { 483 forwardButton.setSelected(true); 484 } else { 485 reverseButton.setSelected(true); 486 } 487 } 488 489 } else if (activeTrain.getMode() == ActiveTrain.MANUAL) { 490 activeTrain.setMode(ActiveTrain.AUTOMATIC); 491 manualButton.setText(Bundle.getMessage("ToManualButton")); 492 manualButton.setToolTipText(Bundle.getMessage("ToManualButtonHint")); 493 manualButton.setVisible(true); 494 forwardButton.setVisible(false); 495 reverseButton.setVisible(false); 496 speedSlider.setVisible(false); 497 autoActiveTrain.restoreSavedSpeedAndDirection(); 498 // autoActiveTrain.setForward(!autoActiveTrain.getRunInReverse()); 499 if ((activeTrain.getStatus() == ActiveTrain.RUNNING) || 500 (activeTrain.getStatus() == ActiveTrain.WAITING)) { 501 autoActiveTrain.setSpeedBySignal(); 502 } 503 } 504 pack(); 505 } 506 507 private JToolBar componentJPanel; 508 509 private void drawComponent() { 510 511 componentJPanel = new JToolBar(); 512 componentJPanel.setLayout(new FlowLayout()); 513 componentJPanel.setFloatable(true); 514 trainLabel = new JLabel(autoActiveTrain.getActiveTrain().getTrainName()); 515 trainLabel.setVisible(true); 516 componentJPanel.add(trainLabel); 517 stopButton = new JButton(Bundle.getMessage("ResumeButton")); 518 componentJPanel.add(stopButton); 519 stopButton.addActionListener(e -> stopResume()); 520 manualButton = new JButton(Bundle.getMessage("ToManualButton")); 521 componentJPanel.add(manualButton); 522 manualButton.addActionListener(e -> manualAutoTrain()); 523 resumeAutoRunningButton = new JButton(Bundle.getMessage("ResumeAutoButton")); 524 componentJPanel.add(resumeAutoRunningButton); 525 resumeAutoRunningButton.addActionListener(e -> resumeAutoOperation()); 526 resumeAutoRunningButton.setVisible(false); 527 resumeAutoRunningButton.setToolTipText(Bundle.getMessage("ResumeAutoButtonHint")); 528 ButtonGroup directionGroup = new ButtonGroup(); 529 forwardButton = new JRadioButton(Bundle.getMessage("ForwardRadio")); 530 componentJPanel.add(forwardButton); 531 forwardButton.addActionListener(e -> directionButton()); 532 directionGroup.add(forwardButton); 533 reverseButton = new JRadioButton(Bundle.getMessage("ReverseRadio")); 534 componentJPanel.add(reverseButton); 535 reverseButton.addActionListener(e -> directionButton()); 536 directionGroup.add(reverseButton); 537 speedSlider = new JSlider(0, 100, 0); 538 speedSlider.setPreferredSize(new Dimension(100, 20)); 539 componentJPanel.add(speedSlider); 540 speedSlider.addChangeListener(e -> { 541 if (speedSlider.isVisible()) { 542 int val = ((JSlider) (e.getSource())).getValue(); 543 float speedValue = val * 0.01f; 544 // bypass auto-engineer limits, ramping etc 545 // when in manual. 546 autoActiveTrain.getThrottle().setSpeedSetting(speedValue); 547 } 548 }); 549 550 throttleStatus = new JLabel(); 551 // prevent JFrame to resize on each % change - temporary size for initialization 552 throttleStatus.setPreferredSize(new Dimension(100, 20)); 553 throttleStatus.setText("Speed Unknown"); 554 componentJPanel.add(throttleStatus); 555 componentJPanel.revalidate(); 556 add(componentJPanel, BorderLayout.EAST); 557 pack(); 558 } 559 560 /* 561 * Using dummy strings get max size of the statustext 562 */ 563 private void setStatusLabelWidth() { 564 if (rosterEntry!=null && autoActiveTrain.getUseSpeedProfile()) { 565 throttleStatus.setPreferredSize( 566 new JTextField(20).getPreferredSize()); 567 } else { 568 throttleStatus.setPreferredSize( 569 new JTextField(10).getPreferredSize()); 570 } 571 } 572 public void stopResume() { 573 if (autoActiveTrain.getAutoEngineer() != null) { 574 ActiveTrain at = autoActiveTrain.getActiveTrain(); 575 if (at.getStatus() == ActiveTrain.STOPPED) { 576 log.trace("Train Is Stopped - Resume"); 577 if (autoActiveTrain.getCurrentBlock().getState() != Block.OCCUPIED) { 578 JmriJOptionPane.showMessageDialog( 579 this, 580 Bundle.getMessage("AutoTrainsFramePleaseMoveTrain",autoActiveTrain.getCurrentBlock().getDisplayName()), 581 Bundle.getMessage("ResumeAutoButton"), 582 JmriJOptionPane.INFORMATION_MESSAGE 583 ); 584 return; 585 } 586 Block b = autoActiveTrain.isBlockAhead(); 587 if (b != null) { 588 JmriJOptionPane.showMessageDialog( 589 this, 590 Bundle.getMessage("AutoTrainsFrameUnExplainedOccupancy", 591 b.getDisplayName(), 592 autoActiveTrain.getNextBlock()), 593 Bundle.getMessage("ResumeAutoButton"), 594 JmriJOptionPane.INFORMATION_MESSAGE 595 ); 596 return; 597 } 598 599 boolean tmpIsForward = true; 600 if ( autoActiveTrain.getRunInReverse() != at.isTransitReversed()) { 601 tmpIsForward = false; 602 } 603 Object[] options = {Bundle.getMessage("AutoTrainsFrameUseImpliedDirection",getDirString(tmpIsForward)), 604 Bundle.getMessage("AutoTrainsFrameRestoreSaved",getDirString(autoActiveTrain.getSavedDirection())), 605 Bundle.getMessage("AutoTrainsFrameUseCurrent",getDirString(autoActiveTrain.getForward())) }; 606 if ( tmpIsForward != autoActiveTrain.getSavedDirection() || 607 tmpIsForward != autoActiveTrain.getForward()) { 608 int retval = JmriJOptionPane.showOptionDialog(this, 609 Bundle.getMessage("AutoTrainsFrameWhichDirectionToUse"), 610 Bundle.getMessage("AutoTrainsFrameDirectionConflict"), 611 JmriJOptionPane.YES_NO_OPTION, 612 JmriJOptionPane.QUESTION_MESSAGE, null, options, options[1]); 613 switch (retval) { 614 case 0: 615 autoActiveTrain.setEngineDirection(tmpIsForward); 616 break; 617 case 1: 618 autoActiveTrain.setEngineDirection(autoActiveTrain.getSavedDirection()); 619 break; 620 case 2: 621 autoActiveTrain.setEngineDirection(autoActiveTrain.getForward()); 622 break; 623 default: 624 // do nothing. 625 log.info("rturneded[{}]",retval); 626 } 627 } 628 autoActiveTrain.getAutoEngineer().setHalt(false); 629 at.setStatus(autoActiveTrain.getSavedStatus()); 630 if (at.getStatus() == ActiveTrain.STOPPED) { 631 at.setStatus(ActiveTrain.WAITING); 632 } 633 if ((at.getStatus() == ActiveTrain.RUNNING) || (at.getStatus() == ActiveTrain.WAITING)) { 634 autoActiveTrain.setSpeedBySignal(); 635 } 636 } else if (at.getStatus() == ActiveTrain.READY) { 637 handleActiveTrainListen(new java.beans.PropertyChangeEvent (this,"status", Integer.valueOf(0), Integer.valueOf(ActiveTrain.READY))); 638 } else if (at.getStatus() == ActiveTrain.DONE) { 639 log.trace("Train Is Done - Restart"); 640 // restart 641 at.allocateAFresh(); 642 at.restart(); 643 } else { 644 log.trace("Process As Stop"); 645 // stop 646 autoActiveTrain.saveSpeedAndDirection(); 647 autoActiveTrain.getAutoEngineer().setHalt(true); 648 autoActiveTrain.setSavedStatus(at.getStatus()); 649 at.setStatus(ActiveTrain.STOPPED); 650 speedSlider.setValue(0); 651 } 652 } else { 653 log.error("unexpected null autoEngineer"); 654 } 655 } 656 657 private String getDirString(boolean isFwd) { 658 return isFwd ? Bundle.getMessage("Fwd") : Bundle.getMessage("Rev"); 659 } 660 661 public void resumeAutoOperation() { 662 autoActiveTrain.resumeAutomaticRunning(); 663 } 664 665 public void directionButton() { 666 ActiveTrain at = autoActiveTrain.getActiveTrain(); 667 if (at.getMode() == ActiveTrain.MANUAL) { 668 autoActiveTrain.setForward(forwardButton.isSelected()); 669 } else { 670 log.debug(" {}:Ignored direction button change, not in manual mode", at.getTrainName()); 671 } 672 } 673 } 674 675 private final static Logger log = LoggerFactory.getLogger(AutoTrainsFrame.class); 676 677} 678 679