001package jmri.jmrix.loconet.locoid;
002
003import javax.swing.BoxLayout;
004import javax.swing.JLabel;
005import javax.swing.JPanel;
006import jmri.jmrix.loconet.LnTrafficController;
007import jmri.jmrix.loconet.LocoNetListener;
008import jmri.jmrix.loconet.LocoNetMessage;
009import jmri.jmrix.loconet.LocoNetSystemConnectionMemo;
010
011/**
012 * User interface for setting the LocoNet ID.
013 *
014 * @author Bob Jacobsen Copyright (C) 2006, 2010
015 */
016public class LocoIdPanel extends jmri.jmrix.loconet.swing.LnPanel implements
017        LocoNetListener {
018
019    // member declarations
020    javax.swing.JButton readButton;
021    javax.swing.JButton setButton;
022    javax.swing.JTextArea value;
023
024    javax.swing.JComboBox<String> idBox;
025    String IDValues[] = {"-", "0", "1", "2", "3", "4", "5", "6", "7"};
026
027    public LocoIdPanel() {
028        super();
029        idBox = new javax.swing.JComboBox<String>(IDValues);
030    }
031
032    /**
033     * {@inheritDoc}
034     */
035    @Override
036    public void initComponents() {
037
038        // Create our UI elements, two buttons and a drop-down.
039        setButton = new javax.swing.JButton(Bundle.getMessage("ButtonSet"));
040        readButton = new javax.swing.JButton(Bundle.getMessage("ButtonRead"));
041
042        // Do our layout, two buttons side by side, drop down below.
043        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
044
045        JPanel p = new JPanel();
046        p.setLayout(new java.awt.FlowLayout());
047        p.add(readButton);
048        p.add(setButton);
049
050        add(p);
051
052        p = new JPanel();
053        p.setLayout(new java.awt.FlowLayout());
054        p.add(new JLabel(Bundle.getMessage("LabelValue")));
055        p.add(idBox);
056
057        add(p);
058
059        // Set our callbacks
060        setButton.addActionListener(new java.awt.event.ActionListener() {
061            @Override
062            public void actionPerformed(java.awt.event.ActionEvent e) {
063                setButtonActionPerformed();
064            }
065        });
066        readButton.addActionListener(new java.awt.event.ActionListener() {
067            @Override
068            public void actionPerformed(java.awt.event.ActionEvent e) {
069                readButtonActionPerformed();
070            }
071        });
072    }
073
074    /**
075     * {@inheritDoc}
076     */
077    @Override
078    public String getHelpTarget() {
079        return "package.jmri.jmrix.loconet.locoid.LocoIdFrame"; // NOI18N
080    }
081
082    /**
083     * {@inheritDoc}
084     */
085    @Override
086    public String getTitle() {
087        return getTitle(Bundle.getMessage("MenuItemSetID"));
088    }
089
090    /**
091     * {@inheritDoc}
092     */
093    @Override
094    public void initComponents(LocoNetSystemConnectionMemo memo) {
095        super.initComponents(memo);
096
097        // connect to the LnTrafficController
098        connect(memo.getLnTrafficController());
099
100        // press the Read button for the user, so we populate the current value
101        readButtonActionPerformed();
102    }
103
104    /**
105     * Callback when someone presses the Set button
106     */
107    public void setButtonActionPerformed() {
108        String value = (String) idBox.getSelectedItem();
109
110        if (!value.equals("-")) {
111            memo.getLnTrafficController().sendLocoNetMessage(
112                    createSetPacket(value));
113        }
114    }
115
116    /**
117     * Callback when someone presses the Read button
118     */
119    public void readButtonActionPerformed() {
120        // We set the display to "-" until the callback gets the value from the
121        // LocoNet
122        idBox.setSelectedIndex(0);
123        memo.getLnTrafficController().sendLocoNetMessage(createReadPacket());
124    }
125
126    /**
127     * Process the incoming message, see if it is a panel response, and if so
128     * parse the LocoNet ID. Use that value to set the ID box.
129     *
130     * This is the callback called by the LnTrafficController
131     *
132     * @param m Inbound LocoNet message to check.
133     */
134    @Override
135    public void message(LocoNetMessage m) {
136
137        // The message is 6 bytes long.
138        if (m.getNumDataElements() != 6) {
139            return;
140        }
141
142        int b1 = m.getOpCode();
143        int b2 = m.getElement(1);
144        int b3 = m.getElement(2);
145        int b4 = m.getElement(3) & 0x07; // UR-92's set bit 4 for duplex
146
147        // Response code is D7 {12, 17, 1F} 00 <value>
148        if ((b1 == 0xD7)
149                && ((b2 == 0x12) || (b2 == 0x17) || (b2 == 0x1F))
150                && (b3 == 0x00)) {
151            // We start with "-", so index + 1
152            idBox.setSelectedIndex(b4 + 1);
153        }
154    }
155
156    /**
157     * Create a LocoNet packet to Query panels for the LocoNet ID
158     *
159     * @return The packet, with contents filled-in
160     */
161    LocoNetMessage createReadPacket() {
162        LocoNetMessage m = new LocoNetMessage(6);
163        m.setElement(0, 0xDF);
164        m.setElement(1, 0x00);
165        m.setElement(2, 0x00);
166        m.setElement(3, 0x00);
167        m.setElement(4, 0x00);
168
169        return m;
170    }
171
172    /**
173     * Create a LocoNet packet to set the LocoNet ID.
174     *
175     * @param s The desired value as a string in decimal
176     * @return The packet, with contents filled-in
177     */
178    LocoNetMessage createSetPacket(String s) {
179        // convert to int value
180        int data = Integer.parseInt(s);
181        // format packet
182        LocoNetMessage m = new LocoNetMessage(6);
183        m.setElement(0, 0xDF);
184        m.setElement(1, 0x40);
185        m.setElement(2, 0x1F);
186        m.setElement(3, data);
187        m.setElement(4, 0x00);
188        return m;
189    }
190
191    /**
192     * Tell the LocoNet controller we want to hear messages, which will
193     * automatically call our "message"
194     *
195     * @param t LocoNet instance to connect to
196     */
197    public void connect(LnTrafficController t) {
198        t.addLocoNetListener(~0, this);
199    }
200
201    /**
202     * {@inheritDoc}
203     */
204    @Override
205    public void dispose() {
206        memo.getLnTrafficController().removeLocoNetListener(~0, this);
207        super.dispose();
208    }
209
210}