001package jmri.jmrix.nce.macro;
002
003import java.awt.Dimension;
004import java.awt.GridBagConstraints;
005import java.awt.GridBagLayout;
006
007import javax.swing.JComponent;
008import javax.swing.JLabel;
009
010import jmri.jmrix.nce.*;
011import jmri.util.swing.JmriJOptionPane;
012
013/**
014 * Pane for user input of NCE macros.
015 *
016 * @author Bob Jacobsen Copyright (C) 2001
017 * @author Dan Boudreau Copyright (C) 2007 Cloned into a Panel by
018 * @author kcameron
019 */
020public class NceMacroGenPanel extends jmri.jmrix.nce.swing.NcePanel implements jmri.jmrix.nce.NceListener {
021
022    // member declarations
023    javax.swing.JLabel jLabel1 = new javax.swing.JLabel(Bundle.getMessage("MacroLabel"));
024    javax.swing.JLabel macroText = new javax.swing.JLabel(Bundle.getMessage("ReplyLabel"));
025    javax.swing.JLabel macroReply = new javax.swing.JLabel();
026    javax.swing.JButton sendButton = new javax.swing.JButton(Bundle.getMessage("Send"));
027    javax.swing.JTextField packetTextField = new javax.swing.JTextField(4);
028
029    // for padding out panel
030    JLabel space1 = new JLabel("                  ");
031    JLabel space3 = new JLabel("                       ");
032
033    private NceTrafficController tc = null;
034
035    public NceMacroGenPanel() {
036        super();
037    }
038
039    /**
040     * {@inheritDoc}
041     */
042    @Override
043    public void initContext(Object context) {
044        if (context instanceof NceSystemConnectionMemo) {
045            initComponents((NceSystemConnectionMemo) context);
046        }
047    }
048
049    /**
050     * {@inheritDoc}
051     */
052    @Override
053    public String getHelpTarget() {
054        return "package.jmri.jmrix.nce.macro.NceMacroEditFrame";
055    }
056
057    /**
058     * {@inheritDoc}
059     */
060    @Override
061    public String getTitle() {
062        StringBuilder x = new StringBuilder();
063        if (memo != null) {
064            x.append(memo.getUserName());
065        } else {
066            x.append("NCE_");
067        }
068        x.append(": ");
069        x.append(Bundle.getMessage("TitleNceMacroGen"));
070        return x.toString();
071    }
072
073    /**
074     * {@inheritDoc}
075     */
076    @Override
077    public void initComponents(NceSystemConnectionMemo memo) {
078        this.memo = memo;
079        tc = memo.getNceTrafficController();
080        // the following code sets the frame's initial state
081
082        // set initial state
083        macroReply.setText(Bundle.getMessage("unknown"));
084
085        // load tool tips
086        sendButton.setToolTipText(Bundle.getMessage("toolTipExecuteMacro"));
087        packetTextField.setToolTipText(Bundle.getMessage("toolTipEnterMacroSerial"));
088
089        packetTextField.setMaximumSize(new Dimension(packetTextField
090                .getMaximumSize().width, packetTextField.getPreferredSize().height));
091
092        setLayout(new GridBagLayout());
093        setPreferredSize(new Dimension(300, 100));
094
095        addItem(jLabel1, 0, 0);
096        addItem(packetTextField, 2, 0);
097        addItem(macroText, 0, 1);
098        addItem(macroReply, 2, 1);
099        //addItem(space1, 0, 2);
100        //addItem(space2, 1, 2);
101        addItem(space3, 2, 2);
102        addItem(sendButton, 0, 3);
103
104        sendButton.addActionListener(new java.awt.event.ActionListener() {
105            @Override
106            public void actionPerformed(java.awt.event.ActionEvent e) {
107                sendButtonActionPerformed(e);
108            }
109        });
110    }
111
112    public void sendButtonActionPerformed(java.awt.event.ActionEvent e) {
113        String input = packetTextField.getText();
114        // TODO check input + feedback on error. Too easy to cause NPE
115        // Send Macro
116        NceMessage m = createMacroCmd(input);
117        if (m == null) {
118            macroReply.setText(Bundle.getMessage("error"));
119            JmriJOptionPane.showMessageDialog(this,
120                    Bundle.getMessage("EnterMacroNumber"),
121                    Bundle.getMessage("NceMacro"),
122                    JmriJOptionPane.ERROR_MESSAGE);
123            return;
124        }
125        macroReply.setText(Bundle.getMessage("waiting"));
126        tc.sendNceMessage(m, this);
127
128        // Unfortunately, the new command doesn't tell us if the macro is empty
129        // so we send old command for status
130        NceMessage m2 = createOldMacroCmd(input);
131        tc.sendNceMessage(m2, this);
132    }
133
134    @Override
135    public void message(NceMessage m) {
136    }  // ignore replies
137
138    @Override
139    public void reply(NceReply r) {
140        if (r.getNumDataElements() == NceMessage.REPLY_1) {
141
142            int recChar = r.getElement(0);
143            if (recChar == NceMessage.NCE_OKAY) {
144                macroReply.setText(Bundle.getMessage("okay"));
145            }
146            if (recChar == '0') {
147                macroReply.setText(Bundle.getMessage("macroEmpty"));
148            }
149
150        } else {
151            macroReply.setText(Bundle.getMessage("error"));
152        }
153    }
154
155    NceMessage createMacroCmd(String s) {
156
157        int macroNum = 0;
158        try {
159            macroNum = Integer.parseInt(s);
160        } catch (NumberFormatException e) {
161            return null;
162        }
163
164        if (macroNum < 0 || macroNum > 255) {
165            return null;
166        }
167
168        if (tc.getCommandOptions() >= NceTrafficController.OPTION_2006) {
169
170            // NCE always responds with okay (!) if macro number is in range.
171            // We need to send this version of macro command to cause turnout
172            // state to change in NCE CS
173            NceMessage m = new NceMessage(5);
174            m.setElement(0, NceMessage.SEND_ACC_SIG_MACRO_CMD);   // Macro cmd
175            m.setElement(1, 0x00);   // addr_h
176            m.setElement(2, 0x01);   // addr_l
177            m.setElement(3, 0x01);   // Macro cmd
178            m.setElement(4, macroNum);  // Macro #
179            m.setBinary(true);
180            m.setReplyLen(NceMessage.REPLY_1);
181            return m;
182
183        } else {
184
185            // NCE responds with okay (!) if macro exist, (0) if not
186            NceMessage m = new NceMessage(2);
187            m.setElement(0, NceMessage.MACRO_CMD);   // Macro cmd
188            m.setElement(1, macroNum);  // Macro #
189            m.setBinary(true);
190            m.setReplyLen(NceMessage.REPLY_1);
191            return m;
192        }
193    }
194
195    NceMessage createOldMacroCmd(String s) {
196
197        int macroNum = 0;
198        try {
199            macroNum = Integer.parseInt(s);
200        } catch (NumberFormatException e) {
201            return null;
202        }
203
204        if (macroNum < 0 || macroNum > 255) {
205            return null;
206        }
207
208        // NCE responds with okay (!) if macro exist, ('0') if not
209        NceMessage m = new NceMessage(2);
210        m.setElement(0, NceMessage.MACRO_CMD); // Macro cmd
211        m.setElement(1, macroNum); // Macro #
212        m.setBinary(true);
213        m.setReplyLen(NceMessage.REPLY_1);
214        return m;
215    }
216
217    private void addItem(JComponent c, int x, int y) {
218        GridBagConstraints gc = new GridBagConstraints();
219        gc.gridx = x;
220        gc.gridy = y;
221        gc.weightx = 100.0;
222        gc.weighty = 100.0;
223        add(c, gc);
224    }
225
226    /**
227     * Nested class to create one of these using old-style defaults.
228     */
229    static public class Default extends jmri.jmrix.nce.swing.NceNamedPaneAction {
230
231        public Default() {
232            super("Open NCE Send Macro Window",
233                    new jmri.util.swing.sdi.JmriJFrameInterface(),
234                    NceMacroGenPanel.class.getName(),
235                    jmri.InstanceManager.getDefault(NceSystemConnectionMemo.class));
236        }
237    }
238
239}