001package jmri.jmrix.can.cbus.swing.console; 002 003import javax.swing.*; 004 005import jmri.jmrix.can.CanMessage; 006import jmri.jmrix.can.CanReply; 007import jmri.jmrix.can.cbus.CbusMessage; 008import jmri.util.swing.JmriJOptionPane; 009import jmri.util.swing.ValidationNotifications; 010 011/** 012 * Frame for CBUS Console 013 * 014 * @author Andrew Crosland Copyright (C) 2008 015 * @author Steve Young Copyright (C) 2018 016 */ 017public class CbusConsolePacketPane extends JPanel { 018 019 private JTextField[] lastRxDataFields; 020 021 private JPanel rxPacketPane; 022 private JPanel sendPacketPane; 023 024 private JTextField lastDynPriField; 025 private JTextField lastMinPriField; 026 027 private JTextField dynPriField; 028 private JTextField minPriField; 029 private JTextField[] dataFields; 030 private JButton sendPacketButton; 031 private JButton dataClearButton; 032 033 private JButton copyButton; 034 private JCheckBox decimalCheckBox; 035 private JCheckBox rcvdDecimalCheckBox; 036 private final CbusConsolePane _mainPane; 037 038 public CbusConsolePacketPane(CbusConsolePane mainPane){ 039 super(); 040 _mainPane = mainPane; 041 042 initRxPacketPane(); 043 initSendPacketPane(); 044 initPanel(); 045 } 046 047 private void initPanel(){ 048 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 049 add(rxPacketPane); 050 add(sendPacketPane); 051 052 } 053 054 private void initRxPacketPane() { 055 056 rcvdDecimalCheckBox = new JCheckBox(); 057 rcvdDecimalCheckBox.setText(Bundle.getMessage("ButtonDecimal")); 058 rcvdDecimalCheckBox.setVisible(true); 059 rcvdDecimalCheckBox.setToolTipText(Bundle.getMessage("TooltipDecimal")); 060 rcvdDecimalCheckBox.setSelected(true); 061 062 // Pane for most recently recived packet 063 rxPacketPane = new JPanel(); 064 rxPacketPane.setLayout(new BoxLayout(rxPacketPane, BoxLayout.X_AXIS)); 065 rxPacketPane.setBorder(BorderFactory.createTitledBorder( 066 BorderFactory.createEtchedBorder(), Bundle.getMessage("MostRecentPacketTitle"))); 067 068 copyButton = new JButton(); 069 copyButton.setText(Bundle.getMessage("ButtonCopy")); 070 copyButton.setVisible(true); 071 copyButton.setToolTipText(Bundle.getMessage("TooltipCopyEvent")); 072 073 copyButton.addActionListener(this::copyButtonActionPerformed); 074 075 initRxPriorityFields(); 076 077 initRxTextFields(); 078 079 } 080 081 private void initSendPacketPane() { 082 083 decimalCheckBox = new JCheckBox(); 084 decimalCheckBox.setText(Bundle.getMessage("ButtonDecimal")); 085 decimalCheckBox.setVisible(true); 086 decimalCheckBox.setToolTipText(Bundle.getMessage("TooltipDecimal")); 087 decimalCheckBox.setSelected(true); 088 089 // Pane for constructing packet to send 090 sendPacketPane = new JPanel(); 091 sendPacketPane.setLayout(new BoxLayout(sendPacketPane, BoxLayout.X_AXIS)); 092 sendPacketPane.setBorder(BorderFactory.createTitledBorder( 093 BorderFactory.createEtchedBorder(), Bundle.getMessage("SendPacketTitle"))); 094 095 // Construct data fields for Priority and up to 8 bytes 096 dynPriField = new JTextField("2", 4); 097 dynPriField.setToolTipText(Bundle.getMessage("TooltipDynPri")); 098 dynPriField.setBorder(BorderFactory.createTitledBorder( 099 BorderFactory.createEtchedBorder(), Bundle.getMessage("DynPriTitle"))); 100 sendPacketPane.add(dynPriField); 101 minPriField = new JTextField("3", 4); 102 minPriField.setToolTipText(Bundle.getMessage("TooltipDinPri03")); 103 minPriField.setBorder(BorderFactory.createTitledBorder( 104 BorderFactory.createEtchedBorder(), Bundle.getMessage("MinPriTitle"))); 105 sendPacketPane.add(minPriField); 106 107 initSendFields(); 108 109 } 110 111 private void initSendFields() { 112 113 sendPacketButton = new JButton(); 114 dataClearButton = new JButton(); 115 116 setupTextFields(dataFields = new JTextField[8],sendPacketPane); 117 118 sendPacketPane.add(sendPacketButton); 119 sendPacketPane.add(dataClearButton); 120 sendPacketPane.add(decimalCheckBox); 121 122 initButtonBorderToolTips(); 123 124 sendPacketButton.addActionListener(this::sendPacketButtonActionPerformed); 125 dataClearButton.addActionListener(this::dataClearButtonActionPerformed); 126 127 } 128 129 130 private void initRxPriorityFields() { 131 132 // Construct data fields for Priority and up to 8 bytes 133 lastDynPriField = new JTextField("", 4); 134 lastDynPriField.setToolTipText(Bundle.getMessage("TooltipDynPri")); 135 lastDynPriField.setBorder(BorderFactory.createTitledBorder( 136 BorderFactory.createEtchedBorder(), Bundle.getMessage("DynPriTitle"))); 137 rxPacketPane.add(lastDynPriField); 138 lastMinPriField = new JTextField("", 4); 139 lastMinPriField.setToolTipText(Bundle.getMessage("TooltipMinPri")); 140 lastMinPriField.setBorder(BorderFactory.createTitledBorder( 141 BorderFactory.createEtchedBorder(), Bundle.getMessage("MinPriTitle"))); 142 rxPacketPane.add(lastMinPriField); 143 144 } 145 146 147 private void initRxTextFields() { 148 149 setupTextFields(lastRxDataFields = new JTextField[8],rxPacketPane); 150 rxPacketPane.add(copyButton); 151 rxPacketPane.add(rcvdDecimalCheckBox); 152 153 } 154 155 private void setupTextFields(JTextField[] data, JPanel panelToAdd) { 156 for (int i = 0; i < 8; i++) { 157 data[i] = new JTextField("", 4); 158 if (i == 0) { 159 data[i].setBorder(BorderFactory.createTitledBorder( 160 BorderFactory.createEtchedBorder(), "d0 (OPC)")); 161 data[i].setToolTipText(Bundle.getMessage("TooltipOpc")); 162 } else { 163 data[i].setBorder(BorderFactory.createTitledBorder( 164 BorderFactory.createEtchedBorder(), "d" + i)); 165 data[i].setToolTipText(Bundle.getMessage("TooltipDbX", i)); 166 } 167 panelToAdd.add(data[i]); 168 } 169 } 170 171 172 private void copyButtonActionPerformed(java.awt.event.ActionEvent e) { 173 dynPriField.setText(lastDynPriField.getText()); 174 minPriField.setText(lastMinPriField.getText()); 175 for (int j = 0; j < 8; j++) { 176 dataFields[j].setText(lastRxDataFields[j].getText()); 177 } 178 } 179 180 private void initButtonBorderToolTips(){ 181 182 sendPacketButton.setText(Bundle.getMessage("ButtonSend")); 183 sendPacketButton.setVisible(true); 184 sendPacketButton.setToolTipText(Bundle.getMessage("TooltipSendPacket")); 185 186 dataClearButton.setText(Bundle.getMessage("ButtonClear")); 187 dataClearButton.setVisible(true); 188 dataClearButton.setToolTipText(Bundle.getMessage("TooltipClearFields")); 189 190 } 191 192 protected void setLastReceived(CanReply r) { 193 194 if (rcvdDecimalCheckBox.isSelected()) { 195 lastDynPriField.setText(Integer.toString(CbusMessage.getPri(r) / 4)); 196 lastMinPriField.setText(Integer.toString(CbusMessage.getPri(r) & 3)); 197 } else { 198 lastDynPriField.setText(Integer.toHexString(CbusMessage.getPri(r) / 4)); 199 lastMinPriField.setText(Integer.toHexString(CbusMessage.getPri(r) & 3)); 200 } 201 // Pay attention to data length in op-code 202 for (int j = 0; j < (r.getElement(0) >> 5) + 1; j++) { 203 if (rcvdDecimalCheckBox.isSelected()) { 204 lastRxDataFields[j].setText(Integer.toString(r.getElement(j))); 205 } else { 206 lastRxDataFields[j].setText(Integer.toHexString(r.getElement(j))); 207 } 208 } 209 210 } 211 212 private void sendPacketButtonActionPerformed(java.awt.event.ActionEvent e) { 213 CanMessage m = new CanMessage(_mainPane.tc.getCanid()); 214 int data = ValidationNotifications.parseBinDecHexByte(dynPriField.getText(), 2, decimalCheckBox.isSelected(), Bundle.getMessage("DynPriErrorDialog"),_mainPane); 215 if (data == -1) { 216 return; 217 } 218 int data2 = ValidationNotifications.parseBinDecHexByte(minPriField.getText(), 3, decimalCheckBox.isSelected(), Bundle.getMessage("MinPriErrorDialog"),_mainPane); 219 if (data2 == -1) { 220 return; 221 } 222 m.setHeader(data * 4 + data2); 223 224 int j; 225 if ((j = setPacketData(m))<1){ 226 return; 227 } 228 229 // Does the number of data match the opcode? 230 // Subtract one as loop variable will have incremented 231 if ((j - 1) != (opcToSend >> 5)) { 232 JmriJOptionPane.showMessageDialog(_mainPane, Bundle.getMessage("OpcCountErrorDialog", (opcToSend >> 5)), 233 Bundle.getMessage("CbusConsoleTitle"), JmriJOptionPane.ERROR_MESSAGE); 234 return; 235 } 236 m.setNumDataElements(j); 237 238 _mainPane.tc.sendCanMessage(m, null); 239 } 240 241 private int opcToSend; 242 243 private int setPacketData(CanMessage m) { 244 245 int j; 246 for (j = 0; j < 8; j++) { 247 if (!dataFields[j].getText().isEmpty()) { 248 int data = ValidationNotifications.parseBinDecHexByte(dataFields[j].getText(), 255, decimalCheckBox.isSelected(), 249 Bundle.getMessage("DbxErrorDialog", j),_mainPane); 250 if (data == -1) { 251 return -1; 252 } 253 m.setElement(j, data); 254 if (j == 0) { 255 opcToSend = data; // save OPC(d0) for later 256 } 257 } else { 258 if (j == 0) { 259 JmriJOptionPane.showMessageDialog(_mainPane, Bundle.getMessage("OpcErrorDialog"), 260 Bundle.getMessage("CbusConsoleTitle"), JmriJOptionPane.ERROR_MESSAGE); 261 } 262 return j; 263 } 264 } 265 return j; 266 } 267 268 269 private void dataClearButtonActionPerformed(java.awt.event.ActionEvent e) { 270 dynPriField.setText("2"); 271 minPriField.setText("3"); 272 for (int i = 0; i < 8; i++) { 273 dataFields[i].setText(""); 274 } 275 } 276 277 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusConsolePacketPane.class); 278}