001package jmri.jmrix.cmri.serial.serialmon; 002 003import java.awt.*; 004import java.awt.event.ActionEvent; 005import java.awt.event.ItemEvent; 006import java.awt.event.ItemListener; 007import java.util.ArrayList; 008import javax.swing.*; 009import javax.swing.border.Border; 010import javax.swing.border.TitledBorder; 011import javax.swing.table.*; 012import jmri.jmrix.cmri.CMRISystemConnectionMemo; 013import jmri.jmrix.cmri.serial.SerialNode; 014import jmri.jmrix.cmri.serial.SerialTrafficController; 015 016/** 017 * Frame for a message filter for CMRInet network packets. 018 * 019 * @author Chuck Catania Copyright (C) 2016 020 */ 021public class SerialFilterFrame extends jmri.util.JmriJFrame { 022 023 ArrayList<SerialNode> monitorNode = new ArrayList<>(); 024 025 // node table pane items 026 protected JPanel nodeEnablePanel = null; 027 protected Border nodeEableBorder = BorderFactory.createEtchedBorder(); 028 protected Border nodeEableBorderTitled = BorderFactory.createTitledBorder(nodeEableBorder,"Monitor Nodes",TitledBorder.LEFT,TitledBorder.ABOVE_TOP); 029 030 protected Border packetTypesBorder = BorderFactory.createEtchedBorder(); 031 protected Border packetTypesBorderTitled = BorderFactory.createTitledBorder(packetTypesBorder,"Packet Types",TitledBorder.LEFT,TitledBorder.ABOVE_TOP); 032 033 protected Border enabledBorder = BorderFactory.createEtchedBorder(); 034 protected Border enabledBorderTitled = BorderFactory.createTitledBorder(enabledBorder,"Select Nodes",TitledBorder.LEFT,TitledBorder.ABOVE_TOP); 035 036 protected Border packetSelectBorder = BorderFactory.createEtchedBorder(); 037 protected Border packetSelectBorderTitled = BorderFactory.createTitledBorder(packetSelectBorder,"Select Packets",TitledBorder.LEFT,TitledBorder.ABOVE_TOP); 038 039 protected Border mainButtonsBorder = BorderFactory.createEtchedBorder(); 040 protected Border mainButtonsBorderTitled = BorderFactory.createTitledBorder(mainButtonsBorder,""); 041 042 protected JTable nodeTable = null; 043 protected TableModel nodeTableModel = null; 044 045 // button pane items 046 JButton doneButton = new JButton(Bundle.getMessage("DoneButtonText") ); 047 JButton haltPollButton = new JButton(Bundle.getMessage("HaltPollButtonText") ); 048 049 JButton nodeMonitorAll = new JButton(Bundle.getMessage("AllButtonText") ); 050 JButton nodeMonitorNone = new JButton(Bundle.getMessage("NoneButtonText") ); 051 052 JButton packetMonitorAll = new JButton(Bundle.getMessage("AllButtonText") ); 053 JButton packetMonitorNone = new JButton(Bundle.getMessage("NoneButtonText") ); 054 055 // CMRInet packet monitor variables only persistent when running 056 //-------------------------------------------------------------- 057 public static final int monPktInit = 0; // (I) 0x49 Initialize 058 public static final int monPktPoll = 1; // (P) 0x50 Poll 059 public static final int monPktRead = 2; // (R) 0x52 Read 060 public static final int monPktTransmit = 3; // (T) 0x54 Transmit 061 public static final int monPktEOT = 4; // (E) 0x45 EOT 062 public static final int monPktQuery = 5; // (Q) 0x51 Query 063 public static final int monPktDGread = 6; // (D) 0x44 Datagram Read 064 public static final int monPktDGwrite = 7; // (W) 0x57 Datagram Write 065 public static final int monPktDGack = 8; // (A) 0x41 Datagram Ack 066 public static final int monPktCodeline = 9; // (C) 0x43 Code Line 067 public static final int monPktNMRAmast = 10; // (M) 0x4D NMRA Mast 068 public static final int monPktRFE = 11; // (?) 0x3F RFE 069/* 070 public static final int monPktRFE = 12; // RFE 071 public static final int monPktRFE = 13; // RFE 072 public static final int monPktRFE = 14; // RFE 073 public static final int monPktRFE = 15; // RFE 074*/ 075 public static final int numMonPkts = monPktRFE; 076 public static final int lastStdPkt = monPktTransmit+1; 077 // static final int[] monPktTypeID = { 078 // 0x49, 0x50, 0x52, 0x54, 0x45, 079 // 0x51, 0x44, 0x57, 0x41, 0x43, 080 // 0x4D, 0x3F 081 // }; 082 083 ArrayList<JCheckBox> packetChkBoxes = new ArrayList<>(); 084 String packetChkBoxLabels[] = { 085 "(I) Initialize ", 086 "(P) Poll ", 087 "(R) Read ", 088 "(T) Transmit ", 089 "(E) EOT ", 090 "(Q) Query ", 091 "(D) Datagram Read ", 092 "(W) Datagram Write", 093 "(A) Datagram Ack ", 094 "(C) Code Line ", 095 "(M) NMRA Mast ", 096 "RFE " 097 }; 098 099 protected JPanel packetTypes = new JPanel(); 100 101 HandlerClass packetTypeCkBoxHandler = new HandlerClass(); 102 private CMRISystemConnectionMemo _memo = null; 103 104 public SerialFilterFrame(CMRISystemConnectionMemo memo) { 105 super("CMRInet Packet Filter"); 106 _memo = memo; 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override 113 public void initComponents() { 114 initializeNodes(); 115 116 // For the class 117 setLayout(new FlowLayout(FlowLayout.LEFT)); 118 setPreferredSize(new Dimension(620,375)); 119 // setBackground(Color.LIGHT_GRAY); 120 121 // Set up the node filter enable table 122 //------------------------------------ 123 nodeEnablePanel = new JPanel(); 124 nodeEnablePanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 125 126 nodeEnablePanel.setLayout(new BoxLayout(nodeEnablePanel, BoxLayout.LINE_AXIS)); 127 nodeEnablePanel.setBorder(nodeEableBorderTitled); 128 nodeEnablePanel.setBackground(Color.WHITE); 129 130 nodeTableModel = new NodeTableModel(); 131 nodeTable = new JTable(nodeTableModel); 132 133 nodeTable.setPreferredScrollableViewportSize(new Dimension(200,90)); 134 nodeTable.setFillsViewportHeight(true); 135 nodeTable.setShowGrid(true); 136 nodeTable.setGridColor(Color.WHITE); 137 nodeTable.setBackground(Color.WHITE); 138 nodeTable.setRowSelectionAllowed(false); 139 nodeTable.setFont(new Font("Lucida Grande", Font.PLAIN, 13)); 140 nodeTable.setRowHeight(30); 141 nodeTable.getTableHeader().setReorderingAllowed(false); 142 143 // Monitor node enable selection check boxes 144 //------------------------------------------ 145 JScrollPane nodeTableScrollPane = new JScrollPane(nodeTable); 146 nodeEnablePanel.add(nodeTableScrollPane,BorderLayout.LINE_START); 147 148 nodeEnablePanel.setBorder(nodeEableBorderTitled); 149 150 TableColumnModel nodeEableColumnModel = nodeTable.getColumnModel(); 151 152 DefaultTableCellRenderer dtcen = new DefaultTableCellRenderer(); 153 dtcen.setHorizontalAlignment(SwingConstants.CENTER); 154 DefaultTableCellRenderer dtlft = new DefaultTableCellRenderer(); 155 dtlft.setHorizontalAlignment(SwingConstants.LEFT); 156 TableCellRenderer rendererFromHeader = nodeTable.getTableHeader().getDefaultRenderer(); 157 JLabel headerLabel = (JLabel) rendererFromHeader; 158 headerLabel.setHorizontalAlignment(JLabel.CENTER); 159 160 TableColumn nodeaddrColumn = nodeEableColumnModel.getColumn(NodeTableModel.NODEADDR_COLUMN); 161 nodeaddrColumn.setCellRenderer(dtcen); 162 nodeaddrColumn.setResizable(false); 163 164 TableColumn enabledColumn = nodeEableColumnModel.getColumn(NodeTableModel.ENABLED_COLUMN); 165 enabledColumn.setResizable(false); 166 167 nodeEnablePanel.setBorder(nodeEableBorderTitled); 168 nodeEnablePanel.setBackground(Color.WHITE); 169 nodeEnablePanel.setPreferredSize(new Dimension(200,200)); 170 171 nodeTable.setAutoCreateRowSorter(true); 172 nodeTable.getRowSorter().toggleSortOrder(NodeTableModel.NODEADDR_COLUMN); 173 nodeEnablePanel.setVisible(true); 174 175 add(nodeEnablePanel); 176 177 // packet type selection check boxes 178 //---------------------------------- 179 JPanel packetSelectTypes = new JPanel(); 180 packetSelectTypes.setLayout(new GridLayout(0,2)); 181 packetSelectTypes.setPreferredSize(new Dimension(400, 200)); 182 packetSelectTypes.setBorder(packetTypesBorderTitled); 183 packetSelectTypes.setBackground(Color.WHITE); 184 185 // Losd the packet types filter check boxes 186 //----------------------------------------- 187 for (int i=0; i<numMonPkts; i++) 188 { 189 JCheckBox ckbox = new JCheckBox(packetChkBoxLabels[i]); 190 packetChkBoxes.add(ckbox); 191 packetChkBoxes.get(i).addItemListener(packetTypeCkBoxHandler); 192 193 packetChkBoxes.get(i).setVisible(false); 194 packetChkBoxes.get(i).setEnabled(false); 195 packetChkBoxes.get(i).setSelected(false); 196 if (i<lastStdPkt) 197 { 198 packetChkBoxes.get(i).setVisible(true); 199 packetChkBoxes.get(i).setEnabled(true); 200 packetChkBoxes.get(i).setSelected(true); 201 } 202 packetSelectTypes.add(ckbox); 203 } 204 205 packetSelectTypes.setVisible(true); 206 add(packetSelectTypes); 207 208 // node monitor enable button panel 209 //--------------------------------- 210 JPanel enableSelectButtons = new JPanel(); 211 enableSelectButtons.setLayout(new FlowLayout(FlowLayout.CENTER)); 212 enableSelectButtons.setPreferredSize(new Dimension(200, 60)); 213 enableSelectButtons.setBackground(Color.WHITE); 214 enableSelectButtons.setBorder(enabledBorderTitled); 215 216 enableSelectButtons.add(nodeMonitorAll); 217 nodeMonitorAll.setVisible(true); 218 nodeMonitorAll.setToolTipText(Bundle.getMessage("AllButtonTip")); 219 nodeMonitorAll.addActionListener(this::nodeMonitorAllButtonActionPerformed); 220 221 enableSelectButtons.add(nodeMonitorNone); 222 nodeMonitorNone.setVisible(true); 223 nodeMonitorNone.setToolTipText(Bundle.getMessage("NoneButtonTip")); 224 nodeMonitorNone.addActionListener(this::nodeMonitorNoneButtonActionPerformed); 225 226 add(enableSelectButtons); 227 228 229 // packet select enable button panel 230 //---------------------------------- 231 JPanel packetSelectButtons = new JPanel(); 232 packetSelectButtons.setLayout(new FlowLayout(FlowLayout.LEFT)); 233 packetSelectButtons.setPreferredSize(new Dimension(400, 60)); 234 packetSelectButtons.setBackground(Color.WHITE); 235 packetSelectButtons.setBorder(packetSelectBorderTitled); 236 237 packetSelectButtons.add(packetMonitorAll); 238 packetMonitorAll.setVisible(true); 239 packetMonitorAll.setToolTipText(Bundle.getMessage("AllButtonTip")); 240 packetMonitorAll.addActionListener(this::packetMonitorAllButtonActionPerformed); 241 242 packetSelectButtons.add(packetMonitorNone); 243 packetMonitorNone.setVisible(true); 244 packetMonitorNone.setToolTipText(Bundle.getMessage("NoneButtonTip") ); 245 packetMonitorNone.addActionListener(this::packetMonitorNoneButtonActionPerformed); 246 247 add(packetSelectButtons); 248 249 // Main button panel 250 //------------------ 251 JPanel mainButtons = new JPanel(); 252 mainButtons.setLayout(new FlowLayout(FlowLayout.RIGHT)); 253 mainButtons.setPreferredSize(new Dimension(600, 60)); 254 255 haltPollButton.setVisible(true); 256 haltPollButton.setToolTipText(Bundle.getMessage("HaltPollButtonTip")); 257 haltPollButton.addActionListener(this::haltpollButtonActionPerformed); 258 mainButtons.add(haltPollButton); 259 260 mainButtons.add(Box.createRigidArea(new Dimension(30, 0))); 261 262 doneButton.setVisible(true); 263 doneButton.setToolTipText(Bundle.getMessage("DoneButtonTip")); 264 doneButton.addActionListener(this::doneButtonActionPerformed); 265 266 mainButtons.add(doneButton); 267 mainButtons.setVisible(true); 268 add(mainButtons); 269 270 addHelpMenu("package.jmri.jmrix.cmri.serial.serialmon.SerialFilterFrame", true); 271 272 // pack for display 273 //----------------- 274 pack(); 275 276 } 277 278 /** 279 * Method to initialize configured nodes and set up the node select combo box 280 */ 281 public void initializeNodes() { 282 // get all configured nodes 283 SerialNode node = (SerialNode) _memo.getTrafficController().getNode(0); 284 int index = 1; 285 while (node != null) { 286 monitorNode.add(node); 287 node = (SerialNode) _memo.getTrafficController().getNode(index); 288 index++; 289 } 290 } 291 292 /** 293 * Set MonitorNodePackets. 294 * @param e unused. 295 */ 296 public void nodeMonitorAllButtonActionPerformed(ActionEvent e) { 297 for(int i=0; i<monitorNode.size(); i++) { 298 monitorNode.get(i).setMonitorNodePackets(false); 299 nodeTableModel.setValueAt(monitorNode.get(i).getMonitorNodePackets(), i, NodeTableModel.ENABLED_COLUMN); 300 } 301 } 302 303 public void nodeMonitorNoneButtonActionPerformed(ActionEvent e) { 304 for(int i=0; i<monitorNode.size(); i++) { 305 monitorNode.get(i).setMonitorNodePackets(true); 306 nodeTableModel.setValueAt(monitorNode.get(i).getMonitorNodePackets(), i, NodeTableModel.ENABLED_COLUMN); 307 } 308 } 309 310 public void packetMonitorAllButtonActionPerformed(ActionEvent e) { 311 for (int i=0; i<lastStdPkt; i++) { 312 packetChkBoxes.get(i).setSelected(true); 313 } 314 } 315 316 public void packetMonitorNoneButtonActionPerformed(ActionEvent e) { 317 for (int i=0; i<lastStdPkt; i++) { 318 packetChkBoxes.get(i).setSelected(false); 319 } 320 } 321 322 public void doneButtonActionPerformed(ActionEvent e) { 323 setVisible(false); 324 dispose(); 325 } 326 327 /* ---------------------------- */ 328 /* Halt Poll button handler */ 329 /* ---------------------------- */ 330 public void haltpollButtonActionPerformed(ActionEvent e) { 331 SerialTrafficController stc = _memo.getTrafficController(); 332 stc.setPollNetwork(!stc.getPollNetwork()); 333 if (stc.getPollNetwork()) { 334 haltPollButton.setText(Bundle.getMessage("HaltPollingText")); 335 } else { 336 haltPollButton.setText(Bundle.getMessage("StartPollingText")); 337 } 338 } 339 340 // ------------------------------- 341 // cpNode options checkbox handler 342 // ------------------------------- 343 private class HandlerClass implements ItemListener{ 344 @Override 345 public void itemStateChanged(ItemEvent e){ 346 JCheckBox pktTypeChkBox = (JCheckBox) e.getSource(); 347 int pktTypeIndex = 0; 348 SerialNode aNode; 349 do { 350 if (pktTypeChkBox == packetChkBoxes.get(pktTypeIndex)) { 351 for (int i=0; i < monitorNode.size(); i++) { 352 aNode = monitorNode.get(i); 353 if (aNode != null) { 354 aNode.setMonitorPacketBit(pktTypeIndex,(packetChkBoxes.get(pktTypeIndex).isSelected())); 355 } 356 } 357 return; 358 } 359 pktTypeIndex++; 360 } while ( pktTypeIndex < numMonPkts); 361 } 362 } 363 /** 364 * Set up table for displaying bit assignments 365 */ 366 public class NodeTableModel extends AbstractTableModel { 367 @Override 368 public String getColumnName(int c) { 369 return nodeEnableColumnsNames[c]; 370 } 371 @Override 372 public Class<?> getColumnClass(int c) { 373 switch (c) { 374 case NODEADDR_COLUMN: 375 return Integer.class; 376 default: 377 return Boolean.class; 378 } 379 } 380 381 @Override 382 public boolean isCellEditable(int r, int c) { 383 return c != NODEADDR_COLUMN; 384 } 385 386 @Override 387 public int getColumnCount() { 388 return NUMCOLUMNS; 389 } 390 391 @Override 392 public int getRowCount() { 393 return monitorNode.size(); 394 } 395 396 @Override 397 public Object getValueAt(int r, int c) { 398 399 switch (c) { 400 case NODEADDR_COLUMN: 401 return monitorNode.get(r).getNodeAddress(); 402 case ENABLED_COLUMN: 403 return monitorNode.get(r).getMonitorNodePackets(); 404 default: 405 return true; 406 } 407 } 408 409 @Override 410 public void setValueAt(Object value, int r, int c) { 411 if (c == NODEADDR_COLUMN) { 412 monitorNode.get(r).setPollListPosition((Integer) value); 413 } else if (c == ENABLED_COLUMN) { 414 monitorNode.get(r).setMonitorNodePackets(!monitorNode.get(r).getMonitorNodePackets()); 415 } 416 fireTableDataChanged(); 417 } 418 419 public static final int NODEADDR_COLUMN = 0; 420 public static final int ENABLED_COLUMN = 1; 421 public static final int NUMCOLUMNS = ENABLED_COLUMN+1; 422 } 423 424 private final String[] nodeEnableColumnsNames = {"Node", "Monitor"}; 425 426 // private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SerialFilterFrame.class); 427 428}