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