001package jmri.jmrit.simpleprog; 002 003import java.awt.Container; 004import java.awt.GridLayout; 005import javax.swing.Box; 006import javax.swing.BoxLayout; 007import javax.swing.JLabel; 008import javax.swing.JPanel; 009import javax.swing.JSeparator; 010import javax.swing.JSpinner; 011import javax.swing.SpinnerNumberModel; 012import jmri.ProgListener; 013import jmri.Programmer; 014import jmri.jmrit.symbolicprog.SymbolicProgBundle; 015 016/** 017 * Frame providing a simple command station programmer 018 * 019 * @author Bob Jacobsen Copyright (C) 2001, 2007 020 * @author Giorgio Terdina Copyright (C) 2007 021 * @author Daniel Bergqvist Copyright (C) 2021 022 */ 023public class SimpleProgFrame extends jmri.util.JmriJFrame implements jmri.ProgListener { 024 025 /** 026 * GUI member declarations 027 */ 028 javax.swing.JToggleButton readButton = new javax.swing.JToggleButton(); 029 javax.swing.JToggleButton writeButton = new javax.swing.JToggleButton(); 030 // use JSpinner for CV number input 031 SpinnerNumberModel model = new SpinnerNumberModel(1, 1, 1024, 1); // 1024 is highest CV number documented by NMRA as per 2017 032 JSpinner addrField = new JSpinner(model); 033 034 javax.swing.JTextField valField = new javax.swing.JTextField(4); 035 036 jmri.jmrit.progsupport.ProgModePane modePane = new jmri.jmrit.progsupport.ProgModePane(BoxLayout.Y_AXIS); 037 038 javax.swing.ButtonGroup radixGroup = new javax.swing.ButtonGroup(); 039 javax.swing.JRadioButton hexButton = new javax.swing.JRadioButton(); 040 javax.swing.JRadioButton decButton = new javax.swing.JRadioButton(); 041 042 javax.swing.JLabel resultsField = new javax.swing.JLabel(" "); 043 044 public SimpleProgFrame() { 045 super(); 046 047 // configure items for GUI 048 readButton.setText(SymbolicProgBundle.getMessage("READ CV")); 049 readButton.setToolTipText(SymbolicProgBundle.getMessage("READ THE VALUE FROM THE SELECTED CV")); 050 051 writeButton.setText(SymbolicProgBundle.getMessage("WRITE CV")); 052 writeButton.setToolTipText(SymbolicProgBundle.getMessage("WRITE THE VALUE TO THE SELECTED CV")); 053 054 hexButton.setText(SymbolicProgBundle.getMessage("Hexadecimal")); 055 decButton.setText(SymbolicProgBundle.getMessage("Decimal")); 056 decButton.setSelected(true); 057 058 // add the actions to the buttons 059 readButton.addActionListener(this::readPushed); 060 writeButton.addActionListener(this::writePushed); 061 decButton.addActionListener(this::decHexButtonChanged); 062 hexButton.addActionListener(this::decHexButtonChanged); 063 064 resultsField.setAlignmentX(JLabel.CENTER_ALIGNMENT); 065 066 Container contentPane = super.getContentPane(); 067 // general GUI config 068 setTitle(SymbolicProgBundle.getMessage("SIMPLE PROGRAMMER")); 069 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 070 071 // install items in GUI 072 javax.swing.JPanel tPane; // temporary pane for layout 073 javax.swing.JPanel tPane2; 074 075 tPane = new JPanel(); 076 tPane.setLayout(new BoxLayout(tPane, BoxLayout.X_AXIS)); 077 tPane.add(readButton); 078 tPane.add(writeButton); 079 contentPane.add(tPane); 080 081 tPane = new JPanel(); 082 tPane.setLayout(new GridLayout(2, 2)); 083 tPane.add(new JLabel(SymbolicProgBundle.getMessage("CV NUMBER:"))); 084 tPane.add(addrField); // JSpinner 085 tPane.add(new JLabel(SymbolicProgBundle.getMessage("VALUE:"))); 086 tPane.add(valField); 087 contentPane.add(tPane); 088 089 contentPane.add(new JSeparator()); 090 091 tPane = new JPanel(); 092 tPane.setLayout(new BoxLayout(tPane, BoxLayout.X_AXIS)); 093 094 tPane.add(modePane); 095 096 tPane.add(new JSeparator(javax.swing.SwingConstants.VERTICAL)); 097 098 tPane2 = new JPanel(); 099 tPane2.setLayout(new BoxLayout(tPane2, BoxLayout.Y_AXIS)); 100 radixGroup.add(decButton); 101 radixGroup.add(hexButton); 102 tPane2.add(new JLabel(SymbolicProgBundle.getMessage("VALUE IS:"))); 103 tPane2.add(decButton); 104 tPane2.add(hexButton); 105 tPane2.add(Box.createVerticalGlue()); 106 tPane.add(tPane2); 107 108 contentPane.add(tPane); 109 110 contentPane.add(new JSeparator()); 111 112 contentPane.add(resultsField); 113 114 if (modePane.getProgrammer() != null) { 115 readButton.setEnabled(modePane.getProgrammer().getCanRead()); 116 } else { 117 readButton.setEnabled(false); 118 } 119 120 // add help menu to window 121 addHelpMenu("package.jmri.jmrit.simpleprog.SimpleProgFrame", true); 122 123 super.pack(); 124 } 125 126 // utility function to get value, handling radix 127 private int getNewVal() { 128 try { 129 if (decButton.isSelected()) { 130 return Integer.parseInt(valField.getText()); 131 } else { 132 return Integer.parseInt(valField.getText(), 16); 133 } 134 } catch (java.lang.NumberFormatException e) { 135 valField.setText(""); 136 return 0; 137 } 138 } 139 140 private String getNewAddr() { 141 return addrField.getValue() + ""; 142 } 143 144 private String statusCode(int status) { 145 Programmer p = modePane.getProgrammer(); 146 if (status == ProgListener.OK) { 147 return SymbolicProgBundle.getMessage("StateOK"); 148 } 149 if (p == null) { 150 return SymbolicProgBundle.getMessage("StateNoProgrammer"); 151 } else { 152 return p.decodeErrorCode(status); 153 } 154 } 155 156 // listen for messages from the Programmer object 157 @Override 158 public void programmingOpReply(int value, int status) { 159 resultsField.setText(statusCode(status)); 160 161 //operation over, raise the buttons 162 readButton.setSelected(false); 163 writeButton.setSelected(false); 164 165 // capture the read value 166 if (value != -1) // -1 implies nothing being returned 167 { 168 if (decButton.isSelected()) { 169 valField.setText("" + value); 170 } else { 171 valField.setText(Integer.toHexString(value)); 172 } 173 } 174 } 175 176 // handle the buttons being pushed 177 public void readPushed(java.awt.event.ActionEvent e) { 178 Programmer p = modePane.getProgrammer(); 179 if (p == null) { 180 resultsField.setText(SymbolicProgBundle.getMessage("StateNoProgrammer")); 181 readButton.setSelected(false); 182 } else { 183 if (p.getCanRead()) { 184 try { 185 resultsField.setText(SymbolicProgBundle.getMessage("StateReading")); 186 p.readCV(getNewAddr(), this); 187 } catch (jmri.ProgrammerException ex) { 188 resultsField.setText("" + ex); 189 readButton.setSelected(false); 190 } 191 } else { 192 resultsField.setText(SymbolicProgBundle.getMessage("CantReadThisMode")); 193 readButton.setSelected(false); 194 } 195 } 196 } 197 198 public void writePushed(java.awt.event.ActionEvent e) { 199 Programmer p = modePane.getProgrammer(); 200 if (p == null) { 201 resultsField.setText(SymbolicProgBundle.getMessage("StateNoProgrammer")); 202 writeButton.setSelected(false); 203 } else { 204 try { 205 resultsField.setText(SymbolicProgBundle.getMessage("StateWriting")); 206 p.writeCV(getNewAddr(), getNewVal(), this); 207 } catch (jmri.ProgrammerException ex) { 208 resultsField.setText("" + ex); 209 writeButton.setSelected(false); 210 } 211 } 212 } 213 214 // provide simple data conversion if dec or hex button changed 215 public void decHexButtonChanged(java.awt.event.ActionEvent e) { 216 resultsField.setText(SymbolicProgBundle.getMessage("StateOK")); 217 if (valField.getText().equals("")) { 218 return; 219 } 220 int value = 0; 221 try { 222 if (decButton.isSelected()) // convert from hex to dec 223 { 224 value = Integer.valueOf(valField.getText(), 16); 225 } else // convert from dec to hex 226 { 227 value = Integer.parseInt(valField.getText()); 228 } 229 } catch (java.lang.NumberFormatException ee) { 230 resultsField.setText(Bundle.getMessage("ErrorTitle")); 231 } 232 if (value != 0) { 233 if (decButton.isSelected()) { 234 valField.setText(Integer.toString(value)); 235 } else { 236 valField.setText(Integer.toHexString(value)); 237 } 238 } 239 } 240 241 @Override 242 public void dispose() { 243 modePane.dispose(); 244 super.dispose(); 245 } 246 247}