001package jmri.jmrix.rps.swing.soundset;
002
003import java.awt.FlowLayout;
004import java.awt.event.ActionListener;
005import java.beans.PropertyChangeListener;
006import javax.swing.BoxLayout;
007import javax.swing.JButton;
008import javax.swing.JCheckBox;
009import javax.swing.JLabel;
010import javax.swing.JPanel;
011import javax.swing.JSeparator;
012import javax.swing.JTextField;
013import jmri.jmrix.rps.Distributor;
014import jmri.jmrix.rps.Engine;
015import jmri.jmrix.rps.Measurement;
016import jmri.jmrix.rps.MeasurementListener;
017import jmri.jmrix.rps.Reading;
018import jmri.jmrix.rps.ReadingListener;
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022/**
023 * Frame for control of the sound speed for the RPS system.
024 *
025 * @author Bob Jacobsen Copyright (C) 2008
026 */
027public class SoundSetPane extends JPanel
028        implements ReadingListener, MeasurementListener, PropertyChangeListener {
029
030    public SoundSetPane() {
031        super();
032    }
033
034    public void dispose() {
035        // separate from data source
036        Distributor.instance().removeReadingListener(this);
037        Distributor.instance().removeMeasurementListener(this);
038        Engine.instance().removePropertyChangeListener(this);
039    }
040
041    JTextField vsound;
042    JTextField newval;
043    JTextField dist;
044    JTextField id;
045    JTextField rcvr;
046    JTextField speed;
047    JCheckBox auto;
048    JTextField gain;
049
050    @Override
051    public void propertyChange(java.beans.PropertyChangeEvent e) {
052        if (e.getPropertyName().equals("vSound")) {
053            // update sound display
054            vsound.setText(nf.format(e.getNewValue()));
055        }
056    }
057
058    public void initComponents() {
059        // number format
060        nf = java.text.NumberFormat.getInstance();
061        nf.setMinimumFractionDigits(1);
062        nf.setMaximumFractionDigits(5);
063        nf.setGroupingUsed(false);
064
065        // GUI
066        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
067
068        // current value
069        JPanel p = new JPanel();
070        p.setLayout(new FlowLayout());
071        p.add(new JLabel("Current sound velocity: "));
072        vsound = new JTextField(5);
073        vsound.setEnabled(false);
074        vsound.setText(nf.format(Engine.instance().getVSound()));
075        p.add(vsound);
076        this.add(p);
077
078        this.add(new JSeparator());
079
080        // set new value
081        p = new JPanel();
082        p.setLayout(new FlowLayout());
083        p.add(new JLabel("New sound velocity: "));
084        newval = new JTextField(8);
085        p.add(newval);
086        JButton b = new JButton("Set");
087        b.addActionListener(new ActionListener() {
088            @Override
089            public void actionPerformed(java.awt.event.ActionEvent e) {
090                setPushed();
091            }
092        });
093        p.add(b);
094        this.add(p);
095
096        this.add(new JSeparator());
097
098        // calculate new speed
099        p = new JPanel();
100        p.setLayout(new FlowLayout());
101        p.add(new JLabel("Known Distance: "));
102        dist = new JTextField(5);
103        p.add(dist);
104        p.add(new JLabel("Transmitter ID: "));
105        id = new JTextField(5);
106        p.add(id);
107        p.add(new JLabel("Receiver Number: "));
108        rcvr = new JTextField(3);
109        p.add(rcvr);
110        this.add(p);
111        p = new JPanel();
112        p.setLayout(new FlowLayout());
113        p.add(new JLabel("Measured Speed: "));
114        speed = new JTextField(8);
115        speed.setEnabled(false);
116        p.add(speed);
117        auto = new JCheckBox("Auto Set");
118        p.add(auto);
119        p.add(new JLabel("Damping: "));
120        gain = new JTextField(3);
121        gain.setText("10.");
122        p.add(gain);
123        this.add(p);
124
125        // start working
126        Distributor.instance().addReadingListener(this);
127        Distributor.instance().addMeasurementListener(this);
128        Engine.instance().addPropertyChangeListener(this);
129    }
130
131    void setPushed() {
132        double val = Double.parseDouble(newval.getText());
133        Engine.instance().setVSound(val);
134    }
135
136    java.text.NumberFormat nf;
137
138    @Override
139    public void notify(Reading r) {
140        try {
141            // right ID?
142            if (!r.getId().equals(id.getText())) {
143                return;
144            }
145
146            // get the right measurement
147            int i = Integer.parseInt(rcvr.getText());
148            if (i < 1 || i > r.getNValues()) {
149                log.warn("resetting receiver number");
150                rcvr.setText("");
151            }
152            log.debug("Rcvr {} saw {}", i, r.getValue(i));
153            double val = r.getValue(i);
154
155            // can't use speed too small
156            if (val < 100) {
157                log.warn("time too small to use: {}", val);
158                return;
159            }
160
161            // calculate speed
162            double newspeed = Double.parseDouble(dist.getText()) / val;
163            speed.setText(nf.format(newspeed));
164
165            // if auto, do update
166            if (auto.isSelected()) {
167                double g = Double.parseDouble(gain.getText());
168                if (g < 1) {
169                    log.warn("resetting gain from {}", gain.getText());
170                    gain.setText("10.");
171                    return;
172                }
173                double updatedspeed = (newspeed + g * Engine.instance().getVSound()) / (g + 1);
174                Engine.instance().setVSound(updatedspeed);
175            }
176        } catch (Exception e) {
177            log.debug("Error calculating speed: {}", e);
178            speed.setText("");
179        }
180    }
181
182    @Override
183    public void notify(Measurement m) {
184        // don't have to do anything
185    }
186
187    private final static Logger log = LoggerFactory.getLogger(SoundSetPane.class);
188
189}