001package jmri.jmrix.loconet.locostats.swing; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import java.awt.event.ActionEvent; 005import javax.swing.BoxLayout; 006import javax.swing.JButton; 007import javax.swing.JLabel; 008import javax.swing.JPanel; 009import javax.swing.JTextField; 010import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 011import jmri.jmrix.loconet.locostats.LocoBufferIIStatus; 012import jmri.jmrix.loconet.locostats.LocoNetInterfaceStatsListener; 013import jmri.jmrix.loconet.locostats.LocoStatsFunc; 014import jmri.jmrix.loconet.locostats.PR2Status; 015import jmri.jmrix.loconet.locostats.PR3MS100ModeStatus; 016import jmri.jmrix.loconet.locostats.RawStatus; 017import jmri.jmrix.loconet.swing.LnPanel; 018import jmri.util.JmriJFrame; 019import jmri.util.ThreadingUtil; 020import org.slf4j.Logger; 021import org.slf4j.LoggerFactory; 022 023/** 024 * Panel displaying LocoNet interface status information. 025 * <p> 026 * The LocoBuffer family from RR-CirKits and the PRn family from Digitrax use 027 * different formats for the status message. This class detects this from the 028 * reply contents, and displays different panes depending on which message was 029 * received. If the format is not recognised, a raw display format is used. 030 * <p> 031 * Moved from loconet.locobuffer.LocoBufferStatsFrame 032 * <p> 033 * Some of the message formats used in this class are Copyright Digitrax, Inc. 034 * and used with permission as part of the JMRI project. That permission does 035 * not extend to uses in other software products. If you wish to use this code, 036 * algorithm or these message formats outside of JMRI, please contact Digitrax 037 * Inc for separate permission. 038 * 039 * @author Alex Shepherd Copyright (C) 2003 040 * @author Bob Jacobsen Copyright (C) 2008, 2010 041 * @since 2.1.5 042 */ 043public class LocoStatsPanel extends LnPanel implements LocoNetInterfaceStatsListener { 044 045 JPanel lb2Panel; 046 JPanel rawPanel; 047 JPanel pr2Panel; 048 JPanel ms100Panel; 049 boolean updateRequestPending = false; 050 051 LocoStatsFunc stats; 052 053 /** 054 * Provides a path to the help html for this tool 055 * 056 * @return path 057 */ 058 @Override 059 public String getHelpTarget() { 060 return "package.jmri.jmrix.loconet.locostats.LocoStatsFrame"; // NOI18N 061 } 062 063 /** 064 * Provides the string for the title of the window 065 * 066 * This is pulled from the properties file for the LocoNet menu entry for 067 * this tool, to ensure consistency between the menu and the window title. 068 * 069 * @return an internationalized string containing the tool's LocoNet menu name 070 */ 071 @Override 072 public String getTitle() { 073 return getTitle(Bundle.getMessage("MenuItemLocoStats")); 074 } 075 076 /** 077 * Constructor 078 */ 079 public LocoStatsPanel() { 080 super(); 081 } 082 083 /** 084 * GUI initializations 085 */ 086 @Override 087 public void initComponents() { 088 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 089 090 // add GUI items 091 rawPanel = new JPanel(); 092 rawPanel.setLayout(new BoxLayout(rawPanel, BoxLayout.X_AXIS)); 093 rawPanel.add(new JLabel(Bundle.getMessage("LabelRawData"))); 094 rawPanel.add(r1); 095 rawPanel.add(r2); 096 rawPanel.add(r3); 097 rawPanel.add(r4); 098 rawPanel.add(r5); 099 rawPanel.add(r6); 100 rawPanel.add(r7); 101 rawPanel.add(r8); 102 103 lb2Panel = new JPanel(); 104 lb2Panel.setLayout(new BoxLayout(lb2Panel, BoxLayout.X_AXIS)); 105 lb2Panel.add(new JLabel(Bundle.getMessage("LabelVersion"))); 106 lb2Panel.add(version); 107 lb2Panel.add(new JLabel(Bundle.getMessage("LabelBreaks"))); 108 breaks.setPreferredSize(version.getPreferredSize()); 109 lb2Panel.add(breaks); 110 lb2Panel.add(new JLabel(Bundle.getMessage("LabelErrors"))); 111 errors.setPreferredSize(version.getPreferredSize()); 112 lb2Panel.add(errors); 113 114 pr2Panel = new JPanel(); 115 pr2Panel.setLayout(new BoxLayout(pr2Panel, BoxLayout.X_AXIS)); 116 pr2Panel.add(new JLabel(Bundle.getMessage("LabelSerialNumber"))); 117 pr2Panel.add(serial); 118 pr2Panel.add(new JLabel(Bundle.getMessage("LabelPR2Status"))); 119 pr2Panel.add(status); 120 pr2Panel.add(new JLabel(Bundle.getMessage("LabelCurrent"))); 121 pr2Panel.add(current); 122 pr2Panel.add(new JLabel(Bundle.getMessage("LabelHardwareVersion"))); 123 pr2Panel.add(hardware); 124 pr2Panel.add(new JLabel(Bundle.getMessage("LabelSoftwareVersion"))); 125 pr2Panel.add(software); 126 127 ms100Panel = new JPanel(); 128 ms100Panel.setLayout(new BoxLayout(ms100Panel, BoxLayout.X_AXIS)); 129 ms100Panel.add(new JLabel(Bundle.getMessage("LabelGoodCnt"))); 130 ms100Panel.add(goodMsgCnt); 131 ms100Panel.add(new JLabel(Bundle.getMessage("LabelBadCnt"))); 132 ms100Panel.add(badMsgCnt); 133 ms100Panel.add(new JLabel(Bundle.getMessage("LabelMS100Status"))); 134 ms100Panel.add(ms100status); 135 136 add(rawPanel); 137 add(lb2Panel); 138 add(pr2Panel); 139 add(ms100Panel); 140 141 JPanel panel = new JPanel(); 142 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 143 add(updateButton); 144 add(panel); 145 146 // install "update" button handler 147 updateButton.addActionListener((ActionEvent a) -> { 148 requestUpdate(); 149 }); 150 151 // and prep for display 152 lb2Panel.setVisible(false); 153 rawPanel.setVisible(true); 154 pr2Panel.setVisible(false); 155 ms100Panel.setVisible(false); 156 revalidate(); 157 158 // will connect when memo is available 159 } 160 161 /** 162 * Configure LocoNet connection 163 * 164 * @param memo specifies which LocoNet connection is used by this tool 165 */ 166 @Override 167 public void initComponents(LocoNetSystemConnectionMemo memo) { 168 super.initComponents(memo); 169 170 stats = new LocoStatsFunc(memo); 171 stats.addLocoNetInterfaceStatsListener(this); 172 173 // request interface data from interface device 174 requestUpdate(); 175 } 176 177 /** 178 * Destructor 179 */ 180 @Override 181 public void dispose() { 182 // unregister listener 183 stats.removeLocoNetInterfaceStatsListener(this); 184 } 185 186 /** 187 * Send LocoNet request for interface status. 188 * 189 * Performs the send from the "Layout" thread, to avoid GUI-related 190 * threading problems. 191 */ 192 public void requestUpdate() { 193 // Invoke the LocoNet request send on the layout thread, not the GUI thread! 194 // Note - there is no guarantee that the LocoNet message will be sent 195 // before execution returns to this method (but it might). 196 ThreadingUtil.runOnLayoutEventually(()->{ stats.sendLocoNetInterfaceStatusQueryMessage(); }); 197 updateRequestPending = true; 198 log.debug("Sending a ping"); 199 } 200 201 JTextField r1 = new JTextField(5); 202 JTextField r2 = new JTextField(5); 203 JTextField r3 = new JTextField(5); 204 JTextField r4 = new JTextField(5); 205 JTextField r5 = new JTextField(5); 206 JTextField r6 = new JTextField(5); 207 JTextField r7 = new JTextField(5); 208 JTextField r8 = new JTextField(5); 209 210 JTextField serial = new JTextField(6); 211 JTextField status = new JTextField(5); 212 JTextField current = new JTextField(4); 213 JTextField hardware = new JTextField(2); 214 JTextField software = new JTextField(3); 215 216 JTextField goodMsgCnt = new JTextField(5); 217 JTextField badMsgCnt = new JTextField(5); 218 JTextField ms100status = new JTextField(6); 219 220 JTextField version = new JTextField(8); 221 JTextField breaks = new JTextField(6); 222 JTextField errors = new JTextField(6); 223 224 225 JButton updateButton = new JButton(Bundle.getMessage("ButtonTextUpdate")); 226 227 /** 228 * Listener for LocoNet Interface Status changes 229 * 230 * @param o a LocoNetStatus object 231 */ 232 @Override 233 @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", justification = "GUI elements are created such that cast to JmriJFrame this is accurate") 234 public void notifyChangedInterfaceStatus(Object o) { 235 log.debug("Update is being handled:{}", o.toString()); // NOI18N 236 if (!updateRequestPending) { 237 return; 238 } 239 240 if (o.getClass() == LocoBufferIIStatus.class) { 241 LocoBufferIIStatus s = (LocoBufferIIStatus) o; 242 version.setText((Integer.toHexString(s.version))); 243 breaks.setText((Integer.toString(s.breaks))); 244 errors.setText((Integer.toString(s.errors))); 245 lb2Panel.setVisible(true); 246 rawPanel.setVisible(false); 247 ms100Panel.setVisible(false); 248 pr2Panel.setVisible(false); 249 ((JmriJFrame) getRootPane().getParent()).setPreferredSize(null); 250 ((JmriJFrame) getRootPane().getParent()).pack(); 251 } else if (o.getClass() == PR2Status.class) { 252 PR2Status s = (PR2Status) o; 253 serial.setText(Integer.toString(s.serial)); 254 status.setText(Integer.toString(s.status)); 255 current.setText(Integer.toString(s.current)); 256 hardware.setText(Integer.toString(s.hardware)); 257 software.setText(Integer.toString(s.software)); 258 lb2Panel.setVisible(false); 259 rawPanel.setVisible(false); 260 ms100Panel.setVisible(true); 261 pr2Panel.setVisible(true); 262 ((JmriJFrame) getRootPane().getParent()).setPreferredSize(null); 263 ((JmriJFrame) getRootPane().getParent()).pack(); 264 } else if (o.getClass() == PR3MS100ModeStatus.class) { 265 PR3MS100ModeStatus s = (PR3MS100ModeStatus) o; 266 goodMsgCnt.setText(Integer.toString(s.goodMsgCnt)); 267 badMsgCnt.setText(Integer.toString(s.badMsgCnt)); 268 ms100status.setText(Integer.toString(s.ms100status)); 269 lb2Panel.setVisible(false); 270 rawPanel.setVisible(false); 271 ms100Panel.setVisible(true); 272 pr2Panel.setVisible(true); 273 ((JmriJFrame) getRootPane().getParent()).setPreferredSize(null); 274 ((JmriJFrame) getRootPane().getParent()).pack(); 275 } else if (o.getClass() == RawStatus.class) { 276 RawStatus s = (RawStatus)o; 277 r1.setText(Integer.toString(s.raw[0])); 278 r2.setText(Integer.toString(s.raw[1])); 279 r3.setText(Integer.toString(s.raw[2])); 280 r4.setText(Integer.toString(s.raw[3])); 281 r5.setText(Integer.toString(s.raw[4])); 282 r6.setText(Integer.toString(s.raw[5])); 283 r7.setText(Integer.toString(s.raw[6])); 284 r8.setText(Integer.toString(s.raw[7])); 285 lb2Panel.setVisible(false); 286 rawPanel.setVisible(true); 287 ms100Panel.setVisible(false); 288 pr2Panel.setVisible(false); 289 ((JmriJFrame) getRootPane().getParent()).setPreferredSize(null); 290 ((JmriJFrame) getRootPane().getParent()).pack(); 291 } 292 } 293 294 private final static Logger log = LoggerFactory.getLogger(LocoStatsPanel.class); 295 296}