001package jmri.jmrit.ctc; 002 003import java.awt.event.ActionListener; 004import java.beans.PropertyChangeListener; 005import javax.swing.Timer; 006import jmri.Sensor; 007 008/** 009 * 010 * @author Gregory J. Bedlek Copyright (C) 2018, 2019 011 * 012 * This module will "simulate" a code button press when there is none. 013 * 014 * It will delay the simulated pressing of a code button for a duration 015 * specified in the constructor, so that the user can change multiple items 016 * on the CTC panel (ONLY in this O.S. section) before the "code is sent to the field". 017 */ 018public class CodeButtonSimulator { 019 private final NBHSensor _mCodeButtonSensor; 020 private final NBHSensor _mSwitchLeverSensor; 021 private final NBHSensor _mLeftSensor; 022 private final NBHSensor _mNormalSensor; 023 private final NBHSensor _mRightSensor; 024 private final NBHSensor _mDispatcherSensorLockToggle; 025 private final PropertyChangeListener _mAnySensorPropertyChangeListener; 026 private final Timer _mPauseTimer; 027 private final ActionListener _mPauseActionListener; 028 029 public CodeButtonSimulator() { 030 // Used to satisfy test requirement 031 _mCodeButtonSensor = null; 032 _mSwitchLeverSensor = null; 033 _mLeftSensor = null; 034 _mNormalSensor = null; 035 _mRightSensor = null; 036 _mDispatcherSensorLockToggle = null; 037 _mAnySensorPropertyChangeListener = null; 038 _mPauseTimer = null; 039 _mPauseActionListener = null; 040 } 041 042 public CodeButtonSimulator( int pauseTimeInMilliseconds, 043 NBHSensor codeButtonSensor, 044 SwitchDirectionLever switchDirectionLever, 045 SignalDirectionLever signalDirectionLever, 046 TurnoutLock turnoutLock) { 047 _mCodeButtonSensor = codeButtonSensor; 048 if (switchDirectionLever != null) { 049 _mSwitchLeverSensor = switchDirectionLever.getSwitchLeverSensor(); 050 } else { // None, create "fake" one: 051 _mSwitchLeverSensor = new NBHSensor("", "", "", "", true); 052 } 053 if (signalDirectionLever != null) { 054 SignalDirectionLever.LNR_NBHSensors Sensors = signalDirectionLever.getLevers(); 055 _mLeftSensor = Sensors._mLeftSensor; 056 _mNormalSensor = Sensors._mNormalSensor; 057 _mRightSensor = Sensors._mRightSensor; 058 } else { 059 _mLeftSensor = new NBHSensor("", "", "", "", true); 060 _mNormalSensor = new NBHSensor("", "", "", "", true); 061 _mRightSensor = new NBHSensor("", "", "", "", true); 062 } 063 if (turnoutLock != null) { 064 _mDispatcherSensorLockToggle = turnoutLock.getDispatcherSensorLockToggle(); 065 } else { 066 _mDispatcherSensorLockToggle = new NBHSensor("", "", "", "", true); 067 } 068 069 _mAnySensorPropertyChangeListener = (PropertyChangeEvent) -> { anySensorPropertyChangeEvent(); }; 070 _mSwitchLeverSensor.addPropertyChangeListener(_mAnySensorPropertyChangeListener); 071 _mLeftSensor.addPropertyChangeListener(_mAnySensorPropertyChangeListener); 072 _mNormalSensor.addPropertyChangeListener(_mAnySensorPropertyChangeListener); 073 _mRightSensor.addPropertyChangeListener(_mAnySensorPropertyChangeListener); 074 _mDispatcherSensorLockToggle.addPropertyChangeListener(_mAnySensorPropertyChangeListener); 075 _mPauseActionListener = (ActionEvent) -> { pauseActionListener(); }; 076 _mPauseTimer = new Timer(pauseTimeInMilliseconds, _mPauseActionListener); 077 _mPauseTimer.setRepeats(false); 078 } 079 080 public void removeAllListeners() { 081 _mSwitchLeverSensor.removePropertyChangeListener(_mAnySensorPropertyChangeListener); 082 _mLeftSensor.removePropertyChangeListener(_mAnySensorPropertyChangeListener); 083 _mNormalSensor.removePropertyChangeListener(_mAnySensorPropertyChangeListener); 084 _mRightSensor.removePropertyChangeListener(_mAnySensorPropertyChangeListener); 085 _mDispatcherSensorLockToggle.removePropertyChangeListener(_mAnySensorPropertyChangeListener); 086 _mPauseTimer.stop(); 087 _mPauseTimer.removeActionListener(_mPauseActionListener); 088 } 089 090 private void pauseActionListener() { 091 _mPauseTimer.stop(); // Probably already so since it fired and their are no repeats, so it doesn't hurt to do this again in case some idiot wants repeats..... 092 _mCodeButtonSensor.setKnownState(Sensor.ACTIVE); // Cause events to be fired as if code button pressed. 093 _mCodeButtonSensor.setKnownState(Sensor.INACTIVE); // Reset it so that can happen again! 094 } 095 096// If the timer is already running due to some other event prior to us being triggered "in parallel" with our event 097// (i.e. within the pause time interval), then we do nothing here: 098 private void anySensorPropertyChangeEvent() { 099 if (_mPauseTimer.isRunning()) return; // Nothing more, within the timer window. 100 _mPauseTimer.start(); // That's it. 101 } 102}