001package jmri.jmrix.ieee802154.swing.nodeconfig; 002 003import java.awt.Container; 004import java.awt.FlowLayout; 005 006import javax.swing.BorderFactory; 007import javax.swing.BoxLayout; 008import javax.swing.JLabel; 009import javax.swing.JPanel; 010import javax.swing.border.Border; 011 012import jmri.jmrix.ieee802154.IEEE802154Node; 013import jmri.jmrix.ieee802154.IEEE802154TrafficController; 014import jmri.util.swing.JmriJOptionPane; 015 016/** 017 * Frame for user configuration of IEEE 802.15.4 nodes. 018 * Derived from node configuration for c/mri nodes. 019 * 020 * @author Bob Jacobsen Copyright (C) 2004 021 * @author Dave Duchamp Copyright (C) 2004 022 * @author Paul Bender Copyright (C) 2013 023 */ 024public class NodeConfigFrame extends jmri.util.JmriJFrame { 025 026 protected javax.swing.JComboBox<String> nodeAddrField = new javax.swing.JComboBox<String>(); 027 protected javax.swing.JComboBox<String> nodeAddr64Field = new javax.swing.JComboBox<String>(); 028 protected javax.swing.JButton addButton = new javax.swing.JButton(Bundle.getMessage("ButtonAdd")); 029 protected javax.swing.JButton editButton = new javax.swing.JButton(Bundle.getMessage("ButtonEdit")); 030 protected javax.swing.JButton deleteButton = new javax.swing.JButton(Bundle.getMessage("ButtonDelete")); 031 protected javax.swing.JButton doneButton = new javax.swing.JButton(Bundle.getMessage("ButtonDone")); 032 protected javax.swing.JButton updateButton = new javax.swing.JButton(Bundle.getMessage("ButtonUpdate")); 033 protected javax.swing.JButton cancelButton = new javax.swing.JButton(Bundle.getMessage("ButtonCancel")); 034 035 protected javax.swing.JLabel statusText1 = new javax.swing.JLabel(); 036 protected javax.swing.JLabel statusText2 = new javax.swing.JLabel(); 037 protected javax.swing.JLabel statusText3 = new javax.swing.JLabel(); 038 039 protected javax.swing.JPanel panel2 = new JPanel(); 040 protected javax.swing.JPanel panel2a = new JPanel(); 041 042 protected boolean changedNode = false; // true if a node was changed, deleted, or added 043 protected boolean editMode = false; // true if in edit mode 044 045 protected IEEE802154Node curNode = null; // IEEE802154 Node being editted 046 047 protected boolean errorInStatus1 = false; 048 protected boolean errorInStatus2 = false; 049 protected String stdStatus1 = Bundle.getMessage("NotesStd1"); 050 protected String stdStatus2 = Bundle.getMessage("NotesStd2"); 051 protected String stdStatus3 = Bundle.getMessage("NotesStd3"); 052 protected String editStatus1 = Bundle.getMessage("NotesEdit1"); 053 protected String editStatus2 = Bundle.getMessage("NotesEdit2"); 054 protected String editStatus3 = Bundle.getMessage("NotesEdit3"); 055 056 private IEEE802154TrafficController itc = null; 057 058 /** 059 * Constructor method 060 * @param tc connector for node 061 */ 062 public NodeConfigFrame(IEEE802154TrafficController tc) { 063 super(); 064 addHelpMenu("package.jmri.jmrix.ieee802154.swing.nodeconfig.NodeConfigFrame", true); 065 itc = tc; 066 } 067 068 /** 069 * Initialize the config window 070 */ 071 @Override 072 public void initComponents() { 073 setTitle(Bundle.getMessage("WindowTitle")); 074 Container contentPane = getContentPane(); 075 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 076 077 contentPane.add(initAddressPanel()); 078 contentPane.add(initNotesPanel()); 079 contentPane.add(initButtonPanel()); 080 081 082 // pack for display 083 pack(); 084 } 085 086 087 /* 088 * Initilaize the address panel. 089 */ 090 protected JPanel initAddressPanel(){ 091 // Set up node address and node type 092 JPanel panel1 = new JPanel(); 093 panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS)); 094 JPanel panel11 = new JPanel(); 095 panel11.setLayout(new FlowLayout()); 096 panel11.add(new JLabel(Bundle.getMessage("LabelNodeAddress") + " ")); 097 panel11.add(nodeAddrField); 098 nodeAddrField.addActionListener(new java.awt.event.ActionListener() { 099 100 @Override 101 public void actionPerformed(java.awt.event.ActionEvent e) { 102 nodeSelected(); 103 } 104 }); 105 nodeAddrField.setToolTipText(Bundle.getMessage("TipNodeAddress")); 106 panel11.add(new JLabel(Bundle.getMessage("LabelNodeAddress64") + " ")); 107 panel11.add(nodeAddr64Field); 108 nodeAddr64Field.setToolTipText(Bundle.getMessage("TipNodeAddress64")); 109 nodeAddr64Field.addActionListener(new java.awt.event.ActionListener() { 110 111 @Override 112 public void actionPerformed(java.awt.event.ActionEvent e) { 113 nodeAddrField.setSelectedIndex(nodeAddr64Field.getSelectedIndex()); 114 } 115 }); 116 117 initAddressBoxes(); 118 panel1.add(panel11); 119 return panel1; 120 } 121 122 123 /* 124 * Initialize the notes panel. 125 */ 126 protected JPanel initNotesPanel(){ 127 // Set up the notes panel 128 JPanel panel3 = new JPanel(); 129 panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS)); 130 JPanel panel31 = new JPanel(); 131 panel31.setLayout(new FlowLayout()); 132 statusText1.setText(stdStatus1); 133 statusText1.setVisible(true); 134 panel31.add(statusText1); 135 JPanel panel32 = new JPanel(); 136 panel32.setLayout(new FlowLayout()); 137 statusText2.setText(stdStatus2); 138 statusText2.setVisible(true); 139 panel32.add(statusText2); 140 JPanel panel33 = new JPanel(); 141 panel33.setLayout(new FlowLayout()); 142 statusText3.setText(stdStatus3); 143 statusText3.setVisible(true); 144 panel33.add(statusText3); 145 panel3.add(panel31); 146 panel3.add(panel32); 147 panel3.add(panel33); 148 Border panel3Border = BorderFactory.createEtchedBorder(); 149 Border panel3Titled = BorderFactory.createTitledBorder(panel3Border, 150 Bundle.getMessage("BoxLabelNotes")); 151 panel3.setBorder(panel3Titled); 152 return panel3; 153 } 154 155 /* 156 * Initialize the Button panel. 157 */ 158 protected JPanel initButtonPanel(){ 159 // Set up buttons 160 JPanel panel4 = new JPanel(); 161 panel4.setLayout(new FlowLayout()); 162 addButton.setText(Bundle.getMessage("ButtonAdd")); 163 addButton.setVisible(true); 164 addButton.setToolTipText(Bundle.getMessage("TipAddButton")); 165 addButton.addActionListener(new java.awt.event.ActionListener() { 166 @Override 167 public void actionPerformed(java.awt.event.ActionEvent e) { 168 addButtonActionPerformed(); 169 } 170 }); 171 panel4.add(addButton); 172 editButton.setText(Bundle.getMessage("ButtonEdit")); 173 editButton.setVisible(true); 174 editButton.setToolTipText(Bundle.getMessage("TipEditButton")); 175 panel4.add(editButton); 176 editButton.addActionListener(new java.awt.event.ActionListener() { 177 @Override 178 public void actionPerformed(java.awt.event.ActionEvent e) { 179 editButtonActionPerformed(); 180 } 181 }); 182 panel4.add(deleteButton); 183 deleteButton.setText(Bundle.getMessage("ButtonDelete")); 184 deleteButton.setVisible(true); 185 deleteButton.setToolTipText(Bundle.getMessage("TipDeleteButton")); 186 panel4.add(deleteButton); 187 deleteButton.addActionListener(new java.awt.event.ActionListener() { 188 @Override 189 public void actionPerformed(java.awt.event.ActionEvent e) { 190 deleteButtonActionPerformed(); 191 } 192 }); 193 panel4.add(doneButton); 194 doneButton.setText(Bundle.getMessage("ButtonDone")); 195 doneButton.setVisible(true); 196 doneButton.setToolTipText(Bundle.getMessage("TipDoneButton")); 197 panel4.add(doneButton); 198 doneButton.addActionListener(new java.awt.event.ActionListener() { 199 @Override 200 public void actionPerformed(java.awt.event.ActionEvent e) { 201 doneButtonActionPerformed(); 202 } 203 }); 204 panel4.add(updateButton); 205 updateButton.setText(Bundle.getMessage("ButtonUpdate")); 206 updateButton.setVisible(true); 207 updateButton.setToolTipText(Bundle.getMessage("TipUpdateButton")); 208 panel4.add(updateButton); 209 updateButton.addActionListener(new java.awt.event.ActionListener() { 210 @Override 211 public void actionPerformed(java.awt.event.ActionEvent e) { 212 updateButtonActionPerformed(); 213 } 214 }); 215 updateButton.setVisible(false); 216 panel4.add(cancelButton); 217 cancelButton.setText(Bundle.getMessage("ButtonCancel")); 218 cancelButton.setVisible(true); 219 cancelButton.setToolTipText(Bundle.getMessage("TipCancelButton")); 220 panel4.add(cancelButton); 221 cancelButton.addActionListener(new java.awt.event.ActionListener() { 222 @Override 223 public void actionPerformed(java.awt.event.ActionEvent e) { 224 cancelButtonActionPerformed(); 225 } 226 }); 227 cancelButton.setVisible(false); 228 return panel4; 229 } 230 231 /** 232 * Method to handle add button 233 */ 234 public void addButtonActionPerformed() { 235 // create a new Add Frame and display it. 236 jmri.util.JmriJFrame addFrame = new AddNodeFrame(itc); 237 try { 238 addFrame.initComponents(); 239 } catch(Exception ex) { 240 log.error("Exception initializing Frame: {}",ex.toString()); 241 return; 242 } 243 addFrame.setVisible(true); 244 } 245 246 /** 247 * Method to handle edit button 248 */ 249 public void editButtonActionPerformed() { 250 // Find IEEE802154 Node address 251 String nodeAddress = readNodeAddress(); 252 if (nodeAddress.equals("")) { 253 return; 254 } 255 // get the IEEE802154Node corresponding to this node address 256 curNode = (IEEE802154Node) itc.getNodeFromAddress(nodeAddress); 257 if (curNode == null) { 258 statusText1.setText(Bundle.getMessage("Error4")); 259 statusText1.setVisible(true); 260 errorInStatus1 = true; 261 resetNotes2(); 262 return; 263 } 264 265 // create a new Edit Frame and display it. 266 jmri.util.JmriJFrame editFrame = new EditNodeFrame(itc,curNode); 267 try { 268 editFrame.initComponents(); 269 } catch(Exception ex) { 270 log.error("Exception initializing Frame: {}",ex.toString()); 271 return; 272 } 273 editFrame.setVisible(true); 274 275 } 276 277 /** 278 * Method to handle delete button 279 */ 280 public void deleteButtonActionPerformed() { 281 // Find IEEE802154 Node address 282 String nodeAddress = readNodeAddress(); 283 if (nodeAddress.equals("")) { 284 return; 285 } 286 // get the IEEE802154Node corresponding to this node address 287 curNode = (IEEE802154Node) itc.getNodeFromAddress(nodeAddress); 288 if (curNode == null) { 289 statusText1.setText(Bundle.getMessage("Error4")); 290 statusText1.setVisible(true); 291 errorInStatus1 = true; 292 resetNotes2(); 293 return; 294 } 295 // confirm deletion with the user 296 if (JmriJOptionPane.OK_OPTION == JmriJOptionPane.showConfirmDialog( 297 this, Bundle.getMessage("ConfirmDelete1") + "\n" 298 + Bundle.getMessage("ConfirmDelete2"), Bundle.getMessage("ConfirmDeleteTitle"), 299 JmriJOptionPane.OK_CANCEL_OPTION, 300 JmriJOptionPane.WARNING_MESSAGE)) { 301 // delete this node 302 itc.deleteNode(nodeAddress); 303 // provide user feedback 304 resetNotes(); 305 statusText1.setText(Bundle.getMessage("FeedBackDelete") + " " + nodeAddress); 306 errorInStatus1 = true; 307 changedNode = true; 308 } else { 309 // reset as needed 310 resetNotes(); 311 } 312 initAddressBoxes(); 313 } 314 315 /** 316 * Method to handle done button 317 */ 318 public void doneButtonActionPerformed() { 319 if (editMode) { 320 // Reset 321 editMode = false; 322 curNode = null; 323 // Switch buttons 324 addButton.setVisible(true); 325 editButton.setVisible(true); 326 deleteButton.setVisible(true); 327 doneButton.setVisible(true); 328 updateButton.setVisible(false); 329 cancelButton.setVisible(false); 330 } 331 if (changedNode) { 332 // Remind user to Save new configuration 333 JmriJOptionPane.showMessageDialog(this, 334 Bundle.getMessage("Reminder1") + "\n" + Bundle.getMessage("Reminder2"), 335 Bundle.getMessage("ReminderTitle"), 336 JmriJOptionPane.INFORMATION_MESSAGE); 337 } 338 setVisible(false); 339 dispose(); 340 } 341 342 /** 343 * Method to handle update button 344 */ 345 public void updateButtonActionPerformed() { 346 // get node information from window 347 348 // check consistency of node information 349 if (!checkConsistency()) { 350 return; 351 } 352 // update node paramaters 353 setNodeParameters(); 354 changedNode = true; 355 // Reset Edit Mode 356 editMode = false; 357 curNode = null; 358 // Switch buttons 359 addButton.setVisible(true); 360 editButton.setVisible(true); 361 deleteButton.setVisible(true); 362 doneButton.setVisible(true); 363 updateButton.setVisible(false); 364 cancelButton.setVisible(false); 365 // refresh notes panel 366 statusText2.setText(stdStatus2); 367 statusText3.setText(stdStatus3); 368 // provide user feedback 369 statusText1.setText(Bundle.getMessage("FeedBackUpdate") + " " + readNodeAddress()); 370 errorInStatus1 = true; 371 } 372 373 /** 374 * Method to handle cancel button 375 */ 376 public void cancelButtonActionPerformed() { 377 // Reset 378 editMode = false; 379 curNode = null; 380 // Switch buttons 381 addButton.setVisible(true); 382 editButton.setVisible(true); 383 deleteButton.setVisible(true); 384 doneButton.setVisible(true); 385 updateButton.setVisible(false); 386 cancelButton.setVisible(false); 387 // refresh notes panel 388 statusText1.setText(stdStatus1); 389 statusText2.setText(stdStatus2); 390 statusText3.setText(stdStatus3); 391 } 392 393 /** 394 * Method to close the window when the close box is clicked 395 */ 396 @Override 397 public void windowClosing(java.awt.event.WindowEvent e) { 398 doneButtonActionPerformed(); 399 super.windowClosing(e); 400 } 401 402 /** 403 * Method to set node parameters The node must exist, and be in 'curNode' 404 */ 405 protected void setNodeParameters() { 406 } 407 408 /** 409 * Method to reset the notes error after error display 410 */ 411 private void resetNotes() { 412 if (errorInStatus1) { 413 if (editMode) { 414 statusText1.setText(editStatus1); 415 } else { 416 statusText1.setText(stdStatus1); 417 } 418 errorInStatus1 = false; 419 } 420 resetNotes2(); 421 } 422 423 /** 424 * Reset the second line of Notes area 425 */ 426 private void resetNotes2() { 427 if (errorInStatus2) { 428 if (editMode) { 429 statusText1.setText(editStatus2); 430 } else { 431 statusText2.setText(stdStatus2); 432 } 433 errorInStatus2 = false; 434 } 435 } 436 437 /** 438 * Read node address from the nodeAddressField or nodeAddr64Field 439 * as appropriate and return as a string. 440 * 441 * @return String containing the short (two byte) address of the node. 442 * if the two byte node address is either "FF FF" or "FF FE", 443 * returns the long (64 bit) address. 444 */ 445 private String readNodeAddress() { 446 String addr = ""; 447 addr = (String) nodeAddrField.getSelectedItem(); 448 if (addr.equals("FF FF ") || addr.equals("FF FE ")) { 449 addr = (String) nodeAddr64Field.getSelectedItem(); 450 } 451 return (addr); 452 } 453 454 /** 455 * Check for consistency errors by node type Returns 'true' if successful, 456 * 'false' if an error was detected. If an error is detected, a suitable 457 * error message is placed in the Notes area 458 * @return always true 459 */ 460 protected boolean checkConsistency() { 461 return true; 462 } 463 464 // Initialize the drop down box for the address lists. 465 protected void initAddressBoxes() { 466 IEEE802154Node current = null; 467 nodeAddrField.removeAllItems(); 468 nodeAddr64Field.removeAllItems(); 469 for (int i = 0; i < itc.getNumNodes(); i++) { 470 current = (IEEE802154Node) itc.getNode(i); 471 nodeAddrField.insertItemAt(jmri.util.StringUtil.hexStringFromBytes(current.getUserAddress()), i); 472 nodeAddr64Field.insertItemAt(jmri.util.StringUtil.hexStringFromBytes(current.getGlobalAddress()), i); 473 } 474 nodeAddrField.insertItemAt("", 0); 475 nodeAddrField.setEditable(true); 476 nodeAddr64Field.insertItemAt("", 0); 477 } 478 479 // Update the display when the selected node changes. 480 protected void nodeSelected() { 481 nodeAddr64Field.setSelectedIndex(nodeAddrField.getSelectedIndex()); 482 } 483 484 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NodeConfigFrame.class); 485 486}