001package jmri.jmrix.loconet.ds64; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004 005import java.awt.Color; 006import java.awt.Component; 007import java.awt.Container; 008import java.awt.FlowLayout; 009import java.awt.Window; 010import java.awt.event.ActionEvent; 011import java.awt.event.ActionListener; 012import java.awt.event.ItemEvent; 013import java.util.ArrayList; 014import java.util.Collections; 015 016import javax.swing.BoxLayout; 017import javax.swing.ButtonGroup; 018import javax.swing.JCheckBox; 019import javax.swing.JComboBox; 020import javax.swing.JComponent; 021import javax.swing.JLabel; 022import javax.swing.JPanel; 023import javax.swing.JRadioButton; 024import javax.swing.JScrollPane; 025import javax.swing.JSeparator; 026import javax.swing.JTabbedPane; 027import javax.swing.JToggleButton; 028import javax.swing.event.ChangeEvent; 029import javax.swing.event.ChangeListener; 030 031import jmri.jmrix.loconet.AbstractBoardProgPanel; 032import jmri.jmrix.loconet.LnConstants; 033import jmri.jmrix.loconet.LocoNetMessage; 034import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 035import jmri.util.swing.JmriJOptionPane; 036import jmri.util.swing.ValidatedTextField; 037 038/** 039 * A "tabbed" swing panel to display and modify Digitrax DS64 board 040 * configuration. 041 * <p> 042 * The read and write operations require a sequence of operations, which are 043 * handled with a state variable. 044 * <p> 045 * Programming of the DS64 is done via LocoNet configuration messages, so the 046 * DS64 should not be manually put into its programming mode via the DS64 047 * built-in pushbutton while this tool is in use. 048 * <p> 049 * Some of the message formats used in this class are Copyright Digitrax, Inc. 050 * and used with permission as part of the JMRI project. That permission does 051 * not extend to uses in other software products. If you wish to use this code, 052 * algorithm or these message formats outside of JMRI, please contact Digitrax 053 * Inc for separate permission. 054 * <p> 055 * Extensions to include read/write of turnout output addresses and routes are 056 * based on reverse-engineering of DS64 operating characteristics by B. 057 * Milhaupt. As such, this tool may not be compatible with all DS64 devices. 058 * <hr> 059 * This file is part of JMRI. 060 * <p> 061 * JMRI is free software; you can redistribute it and/or modify it under the 062 * terms of version 2 of the GNU General Public License as published by the Free 063 * Software Foundation. See the "COPYING" file for a copy of this license. 064 * <p> 065 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 066 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 067 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 068 * <p> 069 * Based on Revision 1.1 of DS64Panel.java by Bob Jacobsen 070 * 071 * @author Bob Jacobsen Copyright (C) 2002, 2004, 2005, 2007, 2010 072 * @author B. Milhaupt Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 073 */ 074public class Ds64TabbedPanel extends AbstractBoardProgPanel { 075 076 /** 077 * Ds64TabbedPanel constructor when the boardNum is already known. Allows 078 * the instantiating method to specify whether the basic feature 079 * configuration information will be read upon instantiation. 080 * 081 * @param boardNum initial BoardID number 082 * @param readOnInit true to automatically read the basic configuration 083 * info. 084 */ 085 public Ds64TabbedPanel(int boardNum, boolean readOnInit) { 086 super(boardNum, readOnInit, "DS64"); // NOI18N 087 origAccessBoardNum = boardNum; 088 boardNumsEntryValue.add(boardNum); 089 } 090 091 /** 092 * Ds64TabbedPanel constructor when the boardNum is not already known. 093 * <p> 094 * At instantiation, the object will automatically assume BoardID 1 and will 095 * not pre-read the basic board configuration information. 096 */ 097 public Ds64TabbedPanel() { 098 // this is a constructor which is in-place to support legacy applications. 099 this(1, false); 100 } 101 102 /** 103 * Ds64TabbedPanel constructor when the boardNum is already known. 104 * <p> 105 * When instantiated, the object will not automatically read the basic 106 * configuration information. 107 * 108 * @param boardNum initial BoardID number 109 */ 110 public Ds64TabbedPanel(int boardNum) { 111 this(boardNum, false); 112 origAccessBoardNum = boardNum; 113 } 114 int[] boardNumbers; 115 int origAccessBoardNum = 0; 116 ArrayList<Integer> boardNumsEntryValue = new ArrayList<>(); 117 118 /** 119 * Ds64TabbedPanel constructor which may be used when the instantiating 120 * method already has an array of DS64 BoardID numbers; this array is used 121 * to pre-populate the GUI combobox showing BoardID numbers. The first 122 * BoardID number in the array will automatically be selected upon 123 * instantiation. 124 * <p> 125 * When instantiated, the object will automatically read the basic 126 * configuration information if readOnInit is true. 127 * 128 * @param readOnInit true to automatically read the basic configuration info 129 * from the DS64 with BoardID equal to the first value in 130 * the boardNums array 131 * @param boardNums Array of known DS64 BoardID numbers 132 */ 133 public Ds64TabbedPanel(boolean readOnInit, Integer[] boardNums) { 134 this(boardNums[0], readOnInit); 135 log.debug("into DS64 tabbed panel with list of boards of length {}", boardNums.length); // NOI18N 136 log.debug("boardNums[0] = {}", boardNums[0]); // NOI18N 137 origAccessBoardNum = boardNums[0]; 138 boardNumsEntryValue.remove(0); // remove the entry added by Ds64TabbedPanel(int boardNum, boolean readOnInit) 139 for (int boardNum : boardNums) { 140 log.debug("board {}", boardNum); // NOI18N 141 boardNumsEntryValue.add(boardNum); 142 } 143 Collections.sort(boardNumsEntryValue); 144 } 145 146 /** 147 * Ds64TabbedPanel constructor when the boardNum is not known; BoardID 1 is 148 * assumed. 149 * <p> 150 * Allows the instantiating method to specify whether the basic feature 151 * configuration information will be read upon instantiation. 152 * 153 * @param readBoardOnInit true to automatically read the basic configuration 154 * info. 155 */ 156 public Ds64TabbedPanel(boolean readBoardOnInit) { 157 this(1, readBoardOnInit); 158 } 159 160 JPanel generalPanel = null; 161 JPanel opswsPanel = null; 162 JScrollPane opswsScrollPane = null; 163 JTabbedPane generalTabbedPane = null; 164 JTabbedPane routesTabbedPane; 165 JPanel opswsValues = null; 166 JPanel outputAddrsPanel = null; 167 ValidatedTextField outAddr1 = null; 168 JLabel outState1 = null; 169 ValidatedTextField outAddr2 = null; 170 JLabel outState2 = null; 171 ValidatedTextField outAddr3 = null; 172 JLabel outState3 = null; 173 ValidatedTextField outAddr4 = null; 174 JLabel outState4 = null; 175 JPanel[] routePanel; 176 SimpleTurnoutStateEntry[] routeTop; 177 SimpleTurnoutStateEntry[] routeA2; 178 SimpleTurnoutStateEntry[] routeA3; 179 SimpleTurnoutStateEntry[] routeA4; 180 SimpleTurnoutStateEntry[] routeA5; 181 SimpleTurnoutStateEntry[] routeA6; 182 SimpleTurnoutStateEntry[] routeA7; 183 SimpleTurnoutStateEntry[] routeA8; 184 JToggleButton resetRouteButton = null; 185 186 JComboBox<Integer> addressComboBox; 187 188 // output controls 189 JLabel outputTypeLabel; 190 JComboBox<String> outputType; 191 192 JLabel delayTimeLabel; 193 JComboBox<String> delayTime; 194 195 JLabel outputStatesLabel; 196 JComboBox<String> outputStates; 197 198 JLabel startupDelayLabel; 199 JComboBox<String> startupDelay; 200 201 JLabel staticOutputShutoffLabel; 202 JComboBox<String> staticOutputShutoff; 203 204 // command sources 205 JLabel commandTypeLabel; 206 JComboBox<String> commandType; 207 208 JLabel commandSourceLabel; 209 JComboBox<String> commandSource; 210 211 // Crossbuck Flasher controls 212 JCheckBox output1CrossbuckFlasherCheckBox; 213 JCheckBox output2CrossbuckFlasherCheckBox; 214 JCheckBox output3CrossbuckFlasherCheckBox; 215 JCheckBox output4CrossbuckFlasherCheckBox; 216 217 // DS64 routes 218 JLabel routesControlLabel; 219 JComboBox<String> routesControl; 220 221 // local input controls 222 JLabel localControlOfOutputsStyleLabel; 223 JComboBox<String> localControlOfOutputsStyle; 224 225 JLabel sensorMessageTriggerLabel; 226 JComboBox<String> sensorMessageTrigger; 227 228 JComboBox<String> localSensorType; 229 230 JToggleButton factoryResetButton; 231 232 JRadioButtonWithInteger[] opswThrown = new JRadioButtonWithInteger[21]; 233 JRadioButtonWithInteger[] opswClosed = new JRadioButtonWithInteger[21]; 234 235 JPanel sensorMessageTriggerPanel; 236 JPanel localInputControlsPanel; 237 238 @Override 239 public String getHelpTarget() { 240 return "package.jmri.jmrix.loconet.ds64.DS64TabbedPanel"; // NOI18N 241 } 242 243 @Override 244 public String getTitle() { 245 return getTitle(Bundle.getMessage("MenuItemDS64Programmer")); 246 } 247 248 public javax.swing.Timer boardResetResponseTimer = null; 249 250 public void updateGuiBasicOpSw(int index) { 251 if ((index < 1) || (index == 7) || (index > 21)) { 252 return; 253 } 254 if (opsw[index]) { 255 opswThrown[index].setSelected(false); 256 opswClosed[index].setSelected(true); 257 } else { 258 opswThrown[index].setSelected(true); 259 opswClosed[index].setSelected(false); 260 } 261 opswThrown[index].updateUI(); 262 opswClosed[index].updateUI(); 263 } 264 265 /** 266 * Copy from the GUI to the opsw array. 267 * <p> 268 * Used before write operations start. 269 */ 270 @Override 271 protected void copyToOpsw() { 272 // copy over the display 273 opsw[1] = (outputType.getSelectedIndex() == 1); 274 updateGuiBasicOpSw(1); 275 int selection = delayTime.getSelectedIndex(); 276 opsw[2] = ((selection & 0x1) == 1); 277 opsw[3] = ((selection & 0x2) == 2); 278 opsw[4] = ((selection & 0x4) == 4); 279 opsw[5] = ((selection & 0x8) == 8); 280 updateGuiBasicOpSw(2); 281 updateGuiBasicOpSw(3); 282 updateGuiBasicOpSw(4); 283 updateGuiBasicOpSw(5); 284 opsw[6] = (outputStates.getSelectedIndex() == 1); 285 updateGuiBasicOpSw(6); 286 opsw[7] = (isWritingResetOpSw ? resetOpSwVal : false); 287 updateGuiBasicOpSw(7); 288 opsw[8] = startupDelay.getSelectedIndex() == 1; 289 updateGuiBasicOpSw(8); 290 opsw[9] = staticOutputShutoff.getSelectedIndex() == 1; 291 updateGuiBasicOpSw(9); 292 opsw[10] = commandType.getSelectedIndex() == 1; 293 updateGuiBasicOpSw(10); 294 opsw[11] = (routesControl.getSelectedIndex() == 1) || (routesControl.getSelectedIndex() == 3); 295 updateGuiBasicOpSw(11); 296 opsw[12] = (localControlOfOutputsStyle.getSelectedIndex() & 1) == 1; //2 -> OpSw12="c" 297 updateGuiBasicOpSw(12); 298 opsw[13] = (sensorMessageTrigger.getSelectedIndex() == 1); 299 updateGuiBasicOpSw(13); 300 opsw[14] = commandSource.getSelectedIndex() == 1; 301 updateGuiBasicOpSw(14); 302 opsw[15] = (localControlOfOutputsStyle.getSelectedIndex() >= 2); //0 -> OpSw15="c" 303 updateGuiBasicOpSw(15); 304 opsw[16] = routesControl.getSelectedIndex() >= 2; 305 updateGuiBasicOpSw(16); 306 opsw[17] = output1CrossbuckFlasherCheckBox.isSelected(); 307 updateGuiBasicOpSw(17); 308 opsw[18] = output2CrossbuckFlasherCheckBox.isSelected(); 309 updateGuiBasicOpSw(18); 310 opsw[19] = output3CrossbuckFlasherCheckBox.isSelected(); 311 updateGuiBasicOpSw(19); 312 opsw[20] = output4CrossbuckFlasherCheckBox.isSelected(); 313 updateGuiBasicOpSw(20); 314 opsw[21] = localSensorType.getSelectedIndex() == 1; 315 updateGuiBasicOpSw(21); 316 } 317 java.awt.Component colorizedObject; 318 319 @Override 320 protected void updateDisplay() { 321 switch (state) { 322 case 1: 323 outputType.setSelectedIndex((opsw[1] == true) ? 1 : 0); 324 break; 325 case 2: 326 case 3: 327 case 4: 328 case 5: 329 delayTime.setSelectedIndex( 330 ((opsw[2] == true) ? 1 : 0) 331 + ((opsw[3] == true) ? 2 : 0) 332 + ((opsw[4] == true) ? 4 : 0) 333 + ((opsw[5] == true) ? 8 : 0)); 334 break; 335 case 6: 336 outputStates.setSelectedIndex((opsw[6] == true) ? 1 : 0); 337 break; 338 case 8: 339 startupDelay.setSelectedIndex((opsw[8] == true) ? 1 : 0); 340 break; 341 case 9: 342 staticOutputShutoff.setSelectedIndex((opsw[9] == true) ? 1 : 0); 343 break; 344 case 10: 345 commandType.setSelectedIndex((opsw[10] == true) ? 1 : 0); 346 break; 347 case 11: 348 case 16: 349 routesControl.setSelectedIndex((((opsw[16] == true) ? 2 : 0) + (opsw[11] ? 1 : 0))); 350 break; 351 case 15: 352 case 12: 353 localControlOfOutputsStyle.setSelectedIndex(((opsw[15] == true) ? 2 : 0) + (opsw[12] ? 1 : 0)); 354 break; 355 case 13: 356 sensorMessageTrigger.setSelectedIndex((opsw[13] == true) ? 1 : 0); // selection 0 - only for A inputs; 1 - both A and S inputs 357 break; 358 case 14: 359 commandSource.setSelectedIndex((opsw[14] == true) ? 1 : 0); 360 break; 361 case 17: 362 output1CrossbuckFlasherCheckBox.setSelected(opsw[17]); 363 break; 364 case 18: 365 output2CrossbuckFlasherCheckBox.setSelected(opsw[18]); 366 break; 367 case 19: 368 output3CrossbuckFlasherCheckBox.setSelected(opsw[19]); 369 break; 370 case 20: 371 output4CrossbuckFlasherCheckBox.setSelected(opsw[20]); 372 373 break; 374 case 21: 375 localSensorType.setSelectedIndex(opsw[21] ? 1 : 0); 376 break; 377 default: 378 // we are only interested in the states above. Ignore the rest 379 log.debug("Unhandled state code: {}", state); 380 break; 381 } 382 updateUI(); 383 } 384 385 @Override 386 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "Cannot catch an exception without grabbing the exception, but we don't do anything with the exception details.") 387 protected int nextState(int state) { 388 if (isWritingResetOpSw) { 389 if ((state == 7) && (opsw[7] == true)) { 390 opsw[7] = false; 391 return 7; 392 } else if (state == 7) { 393 return 0; 394 } 395 } 396 397 if (onlyOneOperation == true) { 398 onlyOneOperation = false; 399 return 0; 400 } 401 if ((state > 1) 402 && (((isRead == true) && (readAllButton.isSelected() == false)) 403 || ((isRead == false) 404 && ((writeAllButton.isSelected() == false) 405 && (resetRouteButton.isSelected() == false))))) { 406 // handle case where a button is de-selected by the user during the operation 407 408 Color noAccessColor = ValidatedTextField.COLOR_BG_UNEDITED; 409 if ((operationType == OpSwOpType.BasicsRead) 410 || (operationType == OpSwOpType.BasicsWrite)) { 411 unhighlightAllBasicOpSws(); 412 unhighlightAllOutputEntryFields(); 413 unhighlightAllRouteEntryFields(); 414 return 0; 415 } else if ((operationType == OpSwOpType.OutputsRead) 416 || (operationType == OpSwOpType.OutputsWrite) 417 || (operationType == OpSwOpType.Route1Read) 418 || (operationType == OpSwOpType.Route1Write) 419 || (operationType == OpSwOpType.Route2Read) 420 || (operationType == OpSwOpType.Route2Write) 421 || (operationType == OpSwOpType.Route3Read) 422 || (operationType == OpSwOpType.Route3Write) 423 || (operationType == OpSwOpType.Route4Read) 424 || (operationType == OpSwOpType.Route4Write) 425 || (operationType == OpSwOpType.Route5Read) 426 || (operationType == OpSwOpType.Route5Write) 427 || (operationType == OpSwOpType.Route6Read) 428 || (operationType == OpSwOpType.Route6Write) 429 || (operationType == OpSwOpType.Route7Read) 430 || (operationType == OpSwOpType.Route7Write) 431 || (operationType == OpSwOpType.Route8Read) 432 || (operationType == OpSwOpType.Route8Write)) { 433 // handle stopping of indirect access operations 434 if (state == 48) { 435 // for DS64, indirect operations for output addresses or route entries can be 436 // aborted after the first 16 indirect bits are accessed 437 changeComponentBgColor(whichComponent(33, indexToRead), noAccessColor); 438 log.debug("Decided to stop read/write after OpSw 48 because no read/write button selected."); // NOI18N 439 return 0; 440 } else if (state == 64) { 441 // for DS64, indirect operations for output addresses or route entries can be 442 // aborted after the second 16 indirect bits are accessed 443 changeComponentBgColor(whichComponent(49, indexToRead), noAccessColor); 444 log.debug("Decided to stop read/write after OpSw 64 because no read/write button selected."); // NOI18N 445 return 0; 446 } 447 } 448 } 449 450 switch (state) { 451 case 1: { 452 if (colorizedObject == null) { 453 colorizedObject = outputType; 454 } 455 colorizedObject.setBackground(null); 456 isRead = read; 457 indexToRead = 0; 458 if ((operationType == null) 459 || (operationType == OpSwOpType.BasicsRead) 460 || (operationType == OpSwOpType.BasicsWrite)) { 461 colorizedObject = delayTime; 462 colorizedObject.setBackground(Color.blue.brighter()); 463 return 2; 464 } else if ((operationType == OpSwOpType.OutputsRead) 465 || (operationType == OpSwOpType.OutputsWrite)) { 466 indexToRead = 0; 467 read = false; // want to write opSw 25 thru 32 468 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 469 return 25; 470 } else if ((operationType == OpSwOpType.Route1Read) || (operationType == OpSwOpType.Route1Write)) { 471 indexToRead = 16; 472 read = false; // want to write opSw 25 thru 32 473 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 474 return 25; 475 } else if ((operationType == OpSwOpType.Route2Read) || (operationType == OpSwOpType.Route2Write)) { 476 indexToRead = 20; 477 read = false; // want to write opSw 25 thru 32 478 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 479 return 25; 480 } else if ((operationType == OpSwOpType.Route3Read) || (operationType == OpSwOpType.Route3Write)) { 481 indexToRead = 24; 482 read = false; // want to write opSw 25 thru 32 483 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 484 return 25; 485 } else if ((operationType == OpSwOpType.Route4Read) || (operationType == OpSwOpType.Route4Write)) { 486 indexToRead = 28; 487 read = false; // want to write opSw 25 thru 32 488 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 489 return 25; 490 } else if ((operationType == OpSwOpType.Route5Read) || (operationType == OpSwOpType.Route5Write)) { 491 indexToRead = 32; 492 read = false; // want to write opSw 25 thru 32 493 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 494 return 25; 495 } else if ((operationType == OpSwOpType.Route6Read) || (operationType == OpSwOpType.Route6Write)) { 496 indexToRead = 36; 497 read = false; // want to write opSw 25 thru 32 498 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 499 return 25; 500 } else if ((operationType == OpSwOpType.Route7Read) || (operationType == OpSwOpType.Route7Write)) { 501 indexToRead = 40; 502 read = false; // want to write opSw 25 thru 32 503 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 504 return 25; 505 } else if ((operationType == OpSwOpType.Route8Read) || (operationType == OpSwOpType.Route8Write)) { 506 indexToRead = 44; 507 read = false; // want to write opSw 25 thru 32 508 setOpSwIndex(indexToRead); //set values for opSw25 thru 32 to point to correct index 509 return 25; 510 } 511 return 0; 512 } 513 case 2: { 514 if (colorizedObject != null) { 515 colorizedObject.setBackground(null); 516 } 517 colorizedObject = delayTime; 518 colorizedObject.setBackground(Color.blue.brighter()); 519 return 3; 520 } 521 case 3: { 522 if (colorizedObject != null) { 523 colorizedObject.setBackground(null); 524 } 525 colorizedObject = delayTime; 526 colorizedObject.setBackground(Color.blue.brighter()); 527 return 4; 528 } 529 case 4: { 530 if (colorizedObject != null) { 531 colorizedObject.setBackground(null); 532 } 533 colorizedObject = delayTime; 534 colorizedObject.setBackground(Color.blue.brighter()); 535 return 5; 536 } 537 case 5: { 538 if (colorizedObject != null) { 539 colorizedObject.setBackground(null); 540 } 541 colorizedObject = outputStates; 542 colorizedObject.setBackground(Color.blue.brighter()); 543 return 6; 544 } 545 case 6: { 546 if (colorizedObject != null) { 547 colorizedObject.setBackground(null); 548 } 549 colorizedObject = startupDelay; 550 colorizedObject.setBackground(Color.blue.brighter()); 551 return 8;// 7 has to be done last, as it's reset 552 } 553 case 8: { 554 if (colorizedObject != null) { 555 colorizedObject.setBackground(null); 556 } 557 colorizedObject = staticOutputShutoff; 558 colorizedObject.setBackground(Color.blue.brighter()); 559 return 9; 560 } 561 case 9: { 562 if (colorizedObject != null) { 563 colorizedObject.setBackground(null); 564 } 565 colorizedObject = commandType; 566 colorizedObject.setBackground(Color.blue.brighter()); 567 return 10; 568 } 569 case 10: { 570 if (colorizedObject != null) { 571 colorizedObject.setBackground(null); 572 } 573 colorizedObject = routesControl; 574 colorizedObject.setBackground(Color.blue.brighter()); 575 return 11; 576 } 577 case 11: { 578 if (colorizedObject != null) { 579 colorizedObject.setBackground(null); 580 } 581 colorizedObject = localControlOfOutputsStyle; 582 colorizedObject.setBackground(Color.blue.brighter()); 583 return 12; 584 } 585 case 12: { 586 if (colorizedObject != null) { 587 colorizedObject.setBackground(null); 588 } 589 colorizedObject = sensorMessageTrigger; 590 colorizedObject.setBackground(Color.blue.brighter()); 591 return 13; 592 } 593 case 13: { 594 if (colorizedObject != null) { 595 colorizedObject.setBackground(null); 596 } 597 colorizedObject = commandSource; 598 colorizedObject.setBackground(Color.blue.brighter()); 599 return 14; 600 } 601 case 14: { 602 if (colorizedObject != null) { 603 colorizedObject.setBackground(null); 604 } 605 colorizedObject = localControlOfOutputsStyle; 606 colorizedObject.setBackground(Color.blue.brighter()); 607 return 15; 608 } 609 case 15: { 610 if (colorizedObject != null) { 611 colorizedObject.setBackground(null); 612 } 613 colorizedObject = routesControl; 614 colorizedObject.setBackground(Color.blue.brighter()); 615 return 16; 616 } 617 case 16: { 618 if (colorizedObject != null) { 619 colorizedObject.setBackground(null); 620 } 621 colorizedObject = output1CrossbuckFlasherCheckBox; 622 colorizedObject.setBackground(Color.blue.brighter()); 623 return 17; 624 } 625 case 17: { 626 if (colorizedObject != null) { 627 colorizedObject.setBackground(null); 628 } 629 colorizedObject = output2CrossbuckFlasherCheckBox; 630 colorizedObject.setBackground(Color.blue.brighter()); 631 return 18; 632 } 633 case 18: { 634 if (colorizedObject != null) { 635 colorizedObject.setBackground(null); 636 } 637 colorizedObject = output3CrossbuckFlasherCheckBox; 638 colorizedObject.setBackground(Color.blue.brighter()); 639 return 19; 640 } 641 case 19: { 642 if (colorizedObject != null) { 643 colorizedObject.setBackground(null); 644 } 645 colorizedObject = output4CrossbuckFlasherCheckBox; 646 colorizedObject.setBackground(Color.blue.brighter()); 647 return 20; 648 } 649 case 20: { 650 if (colorizedObject != null) { 651 colorizedObject.setBackground(null); 652 } 653 colorizedObject = localSensorType; 654 colorizedObject.setBackground(Color.blue.brighter()); 655 return 21; 656 } 657 case 21: { 658 if (colorizedObject != null) { 659 colorizedObject.setBackground(null); 660 } 661 this.readAllButton.setEnabled(true); 662 this.writeAllButton.setEnabled(true); 663 return 0; 664 } 665 case 22: { 666 return 0; 667 } 668 case 25: 669 case 26: 670 case 27: 671 case 28: 672 case 29: 673 case 30: 674 case 31: { 675 // handle indirect index bits 676 return state + 1; 677 } 678 case 32: { 679 read = isRead; // go back to original mode of operation 680 log.debug("Dealing with index {}", indexToRead); 681 changeGuiElementHighlight(33, indexToRead); 682 if (isRead == true) { 683 return 46; // want to read "out-of-turn" to speed up reads when 684 // a route entry is disabled 685 } else { 686 // prepare values in opsw[] from appropriate write values 687 updateOpswForWrite(indexToRead); 688 return 33; 689 } 690 } 691 case 33: 692 case 34: 693 case 35: 694 case 36: 695 case 37: 696 case 38: 697 case 39: 698 case 40: 699 case 41: 700 case 42: 701 case 43: 702 case 44: 703 case 46: 704 case 47: 705 return state + 1; 706 case 45: 707 if (isRead) { 708 // Have already read OpSws 64-48 and determined that there is 709 // a valid value in bits 33-45. Deal with that velue, then 710 // go to the validity bits for the other half. 711 int extractedDataValue = 0; 712 for (int i = 48; i >= 33; i--) { 713 extractedDataValue = (extractedDataValue << 1) + (opsw[i] ? 1 : 0); 714 } 715 log.debug("Read Index {} value (OpSws 33-48) = 0x{}", indexToRead + 1, Integer.toHexString(extractedDataValue)); 716 updateGuiFromOpSws33_48(); 717 changeGuiElementHighlight(48, indexToRead); // clear the highlighted GUI element 718 719 return 62; // because OpSws 46, 47, and 48 were read "out- 720 // of-turn" for speediness, and also want to read OpSws 721 // 62-64 "out-of-turn" for speediness 722 } else { 723 return 46; 724 } 725 case 48: { 726 changeGuiElementHighlight(48, indexToRead); 727 if (isRead == true) { 728 // For reads, check the upper bits of this "half" to determine 729 // whether or not to read the remaining bits in the "half" 730 731 if ((opsw[47] == false) && (opsw[48] == false)) { 732 // entry is valid, so need to read all opSw bits in [46:33] 733 log.debug("Read of low value in index {} is a valid entry.", indexToRead); // NOI18N 734 return 33; 735 } else { 736 log.debug("Read of low value in index {} is an invalid entry.", indexToRead); // NOI18N 737 // entry is not valid, so do not need to read opSw bits in [46:33] 738 // Do need to update internal opSw bits so that they imply an unused 739 // entry 740 changeGuiElementUnHighlight(48, indexToRead); 741 for (int i = 33; i < 46; ++i) { 742 opsw[i] = true; 743 } 744 opsw[40] = false; 745 746 // need to update the GUI 747 updateGuiFromOpSws33_48(); 748 changeGuiElementHighlight(48, indexToRead); // clear the highlighted GUI element 749 750 return 62; // need to skip ahead to the validity bits of the 751 // next entry 752 } 753 } else { 754 // handle the case for writes 755 756 int extractedDataValue = 0; 757 for (int i = 48; i >= 33; i--) { 758 extractedDataValue = (extractedDataValue << 1) + (opsw[i] ? 1 : 0); 759 } 760 log.debug("Wrote Index {} value (OpSws 33-48) = 0x{}", indexToRead + 1, Integer.toHexString(extractedDataValue)); 761 updateGuiFromOpSws33_48(); 762 switch (indexToRead) { 763 case 0: { 764 // have written a value for output1 - update GUI 765 outAddr1.setLastQueriedValue(outAddr1.getText()); 766 break; 767 } 768 case 1: { 769 // have written a value for output3 - update GUI 770 outAddr3.setLastQueriedValue(outAddr3.getText()); 771 break; 772 } 773 case 16: 774 case 20: 775 case 24: 776 case 28: 777 case 32: 778 case 36: 779 case 40: 780 case 44: { 781 // have written value for Route[n] Top entry - update GUI 782 Integer effectiveIndex = (indexToRead - 12) / 4; 783 routeTop[effectiveIndex].addressField.setLastQueriedValue(routeTop[effectiveIndex].addressField.getText()); 784 try { 785 routeTop[effectiveIndex].setAddress(Integer.parseInt(routeTop[effectiveIndex].addressField.getText())); 786 } catch (NumberFormatException e) { 787 routeTop[effectiveIndex].setIsUnused(); 788 } 789 break; 790 } 791 case 17: 792 case 21: 793 case 25: 794 case 29: 795 case 33: 796 case 37: 797 case 41: 798 case 45: { 799 // have written a value for Route n - update GUI 800 Integer effectiveIndex = (indexToRead - 13) / 4; 801 routeA3[effectiveIndex].addressField.setLastQueriedValue(routeA3[effectiveIndex].addressField.getText()); 802 try { 803 routeA3[effectiveIndex].setAddress(Integer.parseInt(routeA3[effectiveIndex].addressField.getText())); 804 } catch (NumberFormatException e) { 805 routeA3[effectiveIndex].setIsUnused(); 806 807 } 808 break; 809 } 810 case 18: 811 case 22: 812 case 26: 813 case 30: 814 case 34: 815 case 38: 816 case 42: 817 case 46: { 818 // have written a value for Route n - update GUI 819 Integer effectiveIndex = (indexToRead - 14) / 4; 820 routeA5[effectiveIndex].addressField.setLastQueriedValue(routeA5[effectiveIndex].addressField.getText()); 821 try { 822 routeA5[effectiveIndex].setAddress(Integer.parseInt(routeA5[effectiveIndex].addressField.getText())); 823 } catch (NumberFormatException e) { 824 routeA5[effectiveIndex].setIsUnused(); 825 } 826 break; 827 } 828 case 19: 829 case 23: 830 case 27: 831 case 31: 832 case 35: 833 case 39: 834 case 43: 835 case 47: { 836 // have written a value for Route n - update GUI 837 Integer effectiveIndex = (indexToRead - 15) / 4; 838 routeA7[effectiveIndex].addressField.setLastQueriedValue(routeA7[effectiveIndex].addressField.getText()); 839 try { 840 routeA7[effectiveIndex].setAddress(Integer.parseInt(routeA7[effectiveIndex].addressField.getText())); 841 } catch (NumberFormatException e) { 842 routeA7[effectiveIndex].setIsUnused(); 843 } 844 break; 845 } 846 default: 847 log.error("invalid indirectIndex for write: {}", indexToRead); // NOI18N 848 return 0; 849 } 850 return 49; 851 } 852 } 853 case 49: 854 case 50: 855 case 51: 856 case 52: 857 case 53: 858 case 54: 859 case 56: 860 case 57: 861 case 58: 862 case 59: 863 case 60: 864 case 62: 865 case 63: 866 return (state + 1); 867 case 55: 868 return 57; // skip apparantly-unused bit to see if this reduces amount of output state disruption during read 869 case 61: 870 if (isRead) { 871 int extractedDataValue = 0; 872 for (int i = 64; i >= 49; i--) { 873 extractedDataValue = (extractedDataValue << 1) + (opsw[i] ? 1 : 0); 874 } 875 log.debug("Read Index {} value (OpSws 49-64) = 0x{}", indexToRead + 1, Integer.toHexString(extractedDataValue)); 876 updateGuiFromOpSws49_64(); 877 changeGuiElementHighlight(61, indexToRead); 878 return determineNextStateForRead(); 879 } else { 880 return 62; 881 } 882 case 64: { 883 if (isRead == true) { 884 // For reads, check the upper bits of this "half" to determine 885 // whether or not to read the remaining bits in the "half" 886 887 if ((opsw[63] == false) && (opsw[64] == false)) { 888 // entry is valid, so need to read all opSw bits in [62:49] 889 log.debug("Read of high value in index {} is a valid entry.", indexToRead); // NOI18N 890 changeGuiElementUnHighlight(64, indexToRead); 891 return 49; 892 } else { 893 // entry is not valid, so do not need to read opSw bits in [46:33] 894 // Do need to update internal opSw bits so that they imply an unused 895 // entry 896 log.debug("Read of high value in index {} is an invalid entry.", indexToRead); // NOI18N 897 for (int i = 49; i < 62; ++i) { 898 opsw[i] = true; 899 } 900 opsw[56] = false; 901 902 // need to update GUI to show unused value 903 updateGuiFromOpSws49_64(); 904 changeGuiElementHighlight(64, indexToRead); // clear the highlighted GUI element 905 906 return determineNextStateForRead(); 907 } 908 } // end handling of read operation 909 else { 910 //handle write operation 911 // skip to next index, or, if done with indexables, 912 // go to end. 913 changeGuiElementHighlight(64, indexToRead); // clear the highlighted GUI element 914 switch (indexToRead) { 915 case 0: { 916 // have written a value for output2 - update GUI 917 outAddr2.setLastQueriedValue(outAddr2.getText()); 918 outAddr2.repaint(); 919 indexToRead++; 920 read = false; 921 setOpSwIndex(indexToRead); 922 return 25; 923 } 924 case 1: { 925 // have written a value for output4 - update GUI 926 outAddr4.setLastQueriedValue(outAddr4.getText()); 927 outAddr4.repaint(); 928 this.readAllButton.setEnabled(true); 929 this.writeAllButton.setEnabled(true); 930 return 0; 931 } 932 case 16: 933 case 20: 934 case 24: 935 case 28: 936 case 32: 937 case 36: 938 case 40: 939 case 44: { 940 // have written a value for Route n - update GUI 941 Integer effectiveIndex = (indexToRead - 12) / 4; 942 routeA2[effectiveIndex].addressField.setLastQueriedValue(routeA2[effectiveIndex].addressField.getText()); 943 try { 944 routeA2[effectiveIndex].setAddress(Integer.parseInt(routeA2[effectiveIndex].addressField.getText())); 945 } catch (NumberFormatException e) { 946 routeA2[effectiveIndex].setIsUnused(); 947 } 948 indexToRead++; 949 read = false; 950 setOpSwIndex(indexToRead); 951 return 25; 952 } 953 case 17: 954 case 21: 955 case 25: 956 case 29: 957 case 33: 958 case 37: 959 case 41: 960 case 45: { 961 // have written a value for Route n - update GUI 962 Integer effectiveIndex = (indexToRead - 13) / 4; 963 routeA4[effectiveIndex].addressField.setLastQueriedValue(routeA4[effectiveIndex].addressField.getText()); 964 try { 965 routeA4[effectiveIndex].setAddress(Integer.parseInt(routeA4[effectiveIndex].addressField.getText())); 966 } catch (NumberFormatException e) { 967 routeA4[effectiveIndex].setIsUnused(); 968 } 969 indexToRead++; 970 read = false; 971 setOpSwIndex(indexToRead); 972 return 25; 973 } 974 case 18: 975 case 22: 976 case 26: 977 case 30: 978 case 34: 979 case 38: 980 case 42: 981 case 46: { 982 // have written a value for Route n - update GUI 983 Integer effectiveIndex = (indexToRead - 14) / 4; 984 routeA6[effectiveIndex].addressField.setLastQueriedValue(routeA6[effectiveIndex].addressField.getText()); 985 try { 986 routeA6[effectiveIndex].setAddress(Integer.parseInt(routeA6[effectiveIndex].addressField.getText())); 987 } catch (NumberFormatException e) { 988 routeA6[effectiveIndex].setIsUnused(); 989 } 990 indexToRead++; 991 read = false; 992 setOpSwIndex(indexToRead); 993 return 25; 994 } 995 case 19: 996 case 23: 997 case 27: 998 case 31: 999 case 35: 1000 case 39: 1001 case 43: 1002 case 47: { 1003 // have written a value for Route n - update GUI 1004 Integer effectiveIndex = (indexToRead - 15) / 4; 1005 routeA8[effectiveIndex].addressField.setLastQueriedValue(routeA8[effectiveIndex].addressField.getText()); 1006 try { 1007 routeA8[effectiveIndex].setAddress(Integer.parseInt(routeA8[effectiveIndex].addressField.getText())); 1008 } catch (NumberFormatException e) { 1009 routeA8[effectiveIndex].setIsUnused(); 1010 } 1011 indexToRead++; 1012 read = false; 1013 setOpSwIndex(indexToRead); 1014 return 0; 1015 } 1016 default: { 1017 return 0; 1018 } 1019 } 1020 } // end handling for write operations 1021 } 1022 1023 case 7: { 1024 this.readAllButton.setEnabled(true); 1025 this.writeAllButton.setEnabled(true); 1026 log.warn("Board has been reset. The board will now respond at Address 1."); // NOI18N 1027 return 0; 1028 } // done! 1029 default: 1030 log.error("unexpected state {}", state); // NOI18N 1031 this.readAllButton.setEnabled(true); 1032 this.writeAllButton.setEnabled(true); 1033 return 0; 1034 } 1035 } 1036 1037 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", 1038 justification = "False positive on the implied local variable in indexToRead++") 1039 private int determineNextStateForRead() { 1040 switch (indexToRead) { 1041 case 1: { 1042 // have read output addresses 1, 2, 3, and 4. No more to 1043 // read (for this tab of the GUI). 1044 this.readAllButton.setEnabled(true); 1045 this.writeAllButton.setEnabled(true); 1046 return 0; 1047 } 1048 case 0: 1049 case 16: 1050 case 20: 1051 case 24: 1052 case 28: 1053 case 32: 1054 case 36: 1055 case 40: 1056 case 44: 1057 case 17: 1058 case 21: 1059 case 25: 1060 case 29: 1061 case 33: 1062 case 37: 1063 case 41: 1064 case 45: 1065 case 18: 1066 case 22: 1067 case 26: 1068 case 30: 1069 case 34: 1070 case 38: 1071 case 42: 1072 case 46: { 1073 // have read a value for Route n. go to next value if necessary 1074 indexToRead++; 1075 read = false; 1076 setOpSwIndex(indexToRead); 1077 return 25; 1078 } 1079 case 19: 1080 case 23: 1081 case 27: 1082 case 31: 1083 case 35: 1084 case 39: 1085 case 43: 1086 case 47: { 1087 // have read last values for Route n. No next value so stop. 1088 indexToRead++; 1089 read = false; 1090 setOpSwIndex(indexToRead); 1091 return 0; 1092 } 1093 default: 1094 return 0; 1095 } 1096 } 1097 1098 private void changeComponentBgColor(JComponent comp, Color color) { 1099 comp.setBackground(color); 1100 } 1101 1102 private JComponent whichComponent(Integer reportedState, Integer reportedIndexToRead) { 1103 if (reportedState == 33) { 1104 switch (reportedIndexToRead) { 1105 case 0: 1106 return outAddr1; 1107 1108 case 1: 1109 return outAddr3; 1110 1111 case 16: 1112 case 20: 1113 case 24: 1114 case 28: 1115 case 32: 1116 case 36: 1117 case 40: 1118 case 44: 1119 return routeTop[(reportedIndexToRead - 12) / 4].addressField; 1120 1121 case 17: 1122 case 21: 1123 case 25: 1124 case 29: 1125 case 33: 1126 case 37: 1127 case 41: 1128 case 45: 1129 return routeA3[(reportedIndexToRead - 13) / 4].addressField; 1130 1131 case 18: 1132 case 22: 1133 case 26: 1134 case 30: 1135 case 34: 1136 case 38: 1137 case 42: 1138 case 46: 1139 return routeA5[(reportedIndexToRead - 14) / 4].addressField; 1140 1141 case 19: 1142 case 23: 1143 case 27: 1144 case 31: 1145 case 35: 1146 case 39: 1147 case 43: 1148 case 47: 1149 return routeA7[(reportedIndexToRead - 15) / 4].addressField; 1150 1151 default: 1152 return null; 1153 } 1154 } else if (reportedState == 49) { 1155 switch (reportedIndexToRead) { 1156 case 0: 1157 return outAddr2; 1158 1159 case 1: 1160 return outAddr4; 1161 1162 case 16: 1163 case 20: 1164 case 24: 1165 case 28: 1166 case 32: 1167 case 36: 1168 case 40: 1169 case 44: 1170 return routeA2[(reportedIndexToRead - 12) / 4].addressField; 1171 1172 case 17: 1173 case 21: 1174 case 25: 1175 case 29: 1176 case 33: 1177 case 37: 1178 case 41: 1179 case 45: 1180 return routeA4[(reportedIndexToRead - 13) / 4].addressField; 1181 1182 case 18: 1183 case 22: 1184 case 26: 1185 case 30: 1186 case 34: 1187 case 38: 1188 case 42: 1189 case 46: 1190 return routeA6[(reportedIndexToRead - 14) / 4].addressField; 1191 1192 case 19: 1193 case 23: 1194 case 27: 1195 case 31: 1196 case 35: 1197 case 39: 1198 case 43: 1199 case 47: 1200 return routeA8[(reportedIndexToRead - 15) / 4].addressField; 1201 1202 default: 1203 return null; 1204 } 1205 } 1206 return null; 1207 } 1208 1209 private void changeGuiElementUnHighlight(Integer reportedState, Integer reportedIndexToRead) { 1210 log.debug("changedGuiElementUnHiglight st={} index={}", reportedState, reportedIndexToRead); 1211 JComponent jc; 1212 switch (reportedState) { 1213 case 33: 1214 return; 1215 case 45: 1216 case 48: 1217 jc = whichComponent(33, reportedIndexToRead); 1218 if (jc != null) { 1219 changeComponentBgColor(jc, null); // inherit from parent 1220 } 1221 return; 1222 case 61: 1223 case 64: 1224 jc = whichComponent(49, reportedIndexToRead); 1225 if (jc != null) { 1226 changeComponentBgColor(jc, null); // inherit from parent 1227 } 1228 break; 1229 default: 1230 // nothing to do in this case 1231 break; 1232 } 1233 } 1234 1235 private void changeGuiElementHighlight(Integer reportedState, Integer reportedIndexToRead) { 1236 log.debug("changedGuiElementHiglight st={} index={}", reportedState, reportedIndexToRead); 1237 Color accessColor = Color.blue.brighter(); 1238 JComponent jc; 1239 if (reportedState == 33) { 1240 jc = whichComponent(reportedState, reportedIndexToRead); 1241 changeComponentBgColor(jc, accessColor); 1242 } 1243 if (reportedState == 48) { 1244 changeGuiElementUnHighlight(33, reportedIndexToRead); 1245 jc = whichComponent(49, reportedIndexToRead); 1246 if (jc != null) { 1247 changeComponentBgColor(jc, accessColor); 1248 } 1249 } 1250 if (reportedState == 64) { 1251 jc = whichComponent(49, reportedIndexToRead); 1252 changeComponentBgColor(jc, null); // inherit from parent component 1253 } 1254 } 1255 1256 private boolean alreadyKnowThisBoardId(Integer id) { 1257 return (boardNumsEntryValue.contains(id)); 1258 } 1259 1260 private Integer addBoardIdToList(Integer id) { 1261 boardNumsEntryValue.add(boardNumsEntryValue.size(), id); 1262 addressComboBox.removeAllItems(); 1263 Collections.sort(boardNumsEntryValue); 1264 Integer indexOfTargetBoardAddress = 0; 1265 for (Integer index = 0; index < boardNumsEntryValue.size(); ++index) { 1266 if (boardNumsEntryValue.get(index).equals(id)) { 1267 indexOfTargetBoardAddress = index; 1268 } 1269 addressComboBox.addItem(boardNumsEntryValue.get(index)); 1270 } 1271 return indexOfTargetBoardAddress; 1272 } 1273 1274 private void selectBoardIdByIndex(Integer index) { 1275 addressComboBox.setSelectedIndex(index); 1276 } 1277 1278 @Override 1279 public void readAll() { 1280 addrField.setText(addressComboBox.getSelectedItem().toString()); 1281 1282 Integer curAddr = Integer.parseInt(addrField.getText()); 1283 1284 // If a new board address is specified, add it (and sort it) into the current list. 1285 if (!alreadyKnowThisBoardId(curAddr)) { 1286 Integer index = addBoardIdToList(curAddr); 1287 selectBoardIdByIndex(index); 1288 } 1289 if (generalTabbedPane.getSelectedComponent().getClass() == JPanel.class) { 1290 if (((JPanel) generalTabbedPane.getSelectedComponent()) == generalPanel) { 1291 operationType = OpSwOpType.BasicsRead; 1292 } else if (((JPanel) generalTabbedPane.getSelectedComponent()) == outputAddrsPanel) { 1293 operationType = OpSwOpType.OutputsRead; 1294 } 1295 } else if (generalTabbedPane.getSelectedComponent().getClass() == JScrollPane.class) { 1296 if (((JScrollPane) generalTabbedPane.getSelectedComponent()) == opswsScrollPane) { 1297 operationType = OpSwOpType.BasicsRead; 1298 } 1299 } else if (generalTabbedPane.getSelectedComponent().getClass() == JTabbedPane.class) { 1300 if (((JTabbedPane) generalTabbedPane.getSelectedComponent() == routesTabbedPane)) { 1301 if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[1]) { 1302 operationType = OpSwOpType.Route1Read; 1303 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[2]) { 1304 operationType = OpSwOpType.Route2Read; 1305 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[3]) { 1306 operationType = OpSwOpType.Route3Read; 1307 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[4]) { 1308 operationType = OpSwOpType.Route4Read; 1309 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[5]) { 1310 operationType = OpSwOpType.Route5Read; 1311 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[6]) { 1312 operationType = OpSwOpType.Route6Read; 1313 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[7]) { 1314 operationType = OpSwOpType.Route7Read; 1315 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[8]) { 1316 operationType = OpSwOpType.Route8Read; 1317 } else { 1318 log.error("DS64 TabbedPanel into readAll(): no known Route[n] tab selected."); 1319 return; 1320 } 1321 } else { 1322 log.error("DS64 TabbedPanel into ReadAll(): no selected tab group"); 1323 return; 1324 } 1325 } else { 1326 return; 1327 } 1328 super.readAll(); 1329 } 1330 1331 public void updateBoardAddress() { 1332 addrField.setText(addressComboBox.getSelectedItem().toString()); 1333 } 1334 1335 @Override 1336 public void writeAll() { 1337 addrField.setText(addressComboBox.getSelectedItem().toString()); 1338 1339 Integer curAddr = Integer.parseInt(addrField.getText()); 1340 1341 // If a new board address is specified, add it (and sort it) into the current list. 1342 if (!boardNumsEntryValue.contains(curAddr)) { 1343 boardNumsEntryValue.add(boardNumsEntryValue.size(), curAddr); 1344 addressComboBox.removeAllItems(); 1345 Collections.sort(boardNumsEntryValue); 1346 Integer indexOfTargetBoardAddress = 0; 1347 for (Integer index = 0; index < boardNumsEntryValue.size(); ++index) { 1348 if (boardNumsEntryValue.get(index).equals(curAddr)) { 1349 indexOfTargetBoardAddress = index; 1350 } 1351 addressComboBox.addItem(boardNumsEntryValue.get(index)); 1352 } 1353 addressComboBox.setSelectedIndex(indexOfTargetBoardAddress); 1354 } 1355 1356 if (generalTabbedPane.getSelectedComponent().getClass() == JPanel.class) { 1357 if (((JPanel) generalTabbedPane.getSelectedComponent()) == generalPanel) { 1358 operationType = OpSwOpType.BasicsWrite; 1359 } else if (((JPanel) generalTabbedPane.getSelectedComponent()) == outputAddrsPanel) { 1360 operationType = OpSwOpType.OutputsWrite; 1361 } 1362 } else if (generalTabbedPane.getSelectedComponent().getClass() == JScrollPane.class) { 1363 if (((JScrollPane) generalTabbedPane.getSelectedComponent()) == opswsScrollPane) { 1364 operationType = OpSwOpType.BasicsWrite; 1365 } 1366 1367 } else if (generalTabbedPane.getSelectedComponent().getClass() == JTabbedPane.class) { 1368 if (((JTabbedPane) generalTabbedPane.getSelectedComponent()) == routesTabbedPane) { 1369 1370 if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[1]) { 1371 operationType = OpSwOpType.Route1Write; 1372 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[2]) { 1373 operationType = OpSwOpType.Route2Write; 1374 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[3]) { 1375 operationType = OpSwOpType.Route3Write; 1376 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[4]) { 1377 operationType = OpSwOpType.Route4Write; 1378 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[5]) { 1379 operationType = OpSwOpType.Route5Write; 1380 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[6]) { 1381 operationType = OpSwOpType.Route6Write; 1382 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[7]) { 1383 operationType = OpSwOpType.Route7Write; 1384 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[8]) { 1385 operationType = OpSwOpType.Route8Write; 1386 } else { 1387 return; 1388 } 1389 } else { 1390 return; 1391 } 1392 } else { 1393 return; 1394 } 1395 1396 super.writeAll(); 1397 } 1398 1399 private enum OpSwOpType { 1400 OutputsRead, OutputsWrite, 1401 Route1Read, Route1Write, 1402 Route2Read, Route2Write, 1403 Route3Read, Route3Write, 1404 Route4Read, Route4Write, 1405 Route5Read, Route5Write, 1406 Route6Read, Route6Write, 1407 Route7Read, Route7Write, 1408 Route8Read, Route8Write, 1409 BasicsRead, BasicsWrite 1410 } 1411 1412 private OpSwOpType operationType = null; 1413 Boolean isRead; 1414 Boolean isWritingResetOpSw = false; 1415 Integer indexToRead = 0; 1416 Boolean resetOpSwVal = false; 1417 1418 /** 1419 * Set index into OpSw table 1420 * 1421 * @param index the indirect address 1422 */ 1423 protected void setOpSwIndex(int index) { 1424 opsw[25] = (index & 1) == 1; 1425 opsw[26] = (index & 2) == 2; 1426 opsw[27] = (index & 4) == 4; 1427 opsw[28] = (index & 8) == 8; 1428 opsw[29] = (index & 16) == 16; 1429 opsw[30] = (index & 32) == 32; 1430 opsw[31] = (index & 64) == 64; 1431 opsw[32] = (index & 128) == 128; 1432 } 1433 1434 /** 1435 * Updates data register to reflect address, state, and enable for two 1436 * turnouts. 1437 * 1438 * @param address1 first turnout address 1439 * @param state1 first turnout's state 1440 * @param is1Unused true if first turnout entry is to be "unused" 1441 * @param address2 second turnout address 1442 * @param state2 second turnout's state 1443 * @param is2Unused true if second turnout entry is to be "unused" 1444 */ 1445 protected void updateOpSwsOutAddr(int address1, boolean state1, boolean is1Unused, int address2, boolean state2, boolean is2Unused) { 1446 int addr1 = address1 - 1; 1447 int addr2 = address2 - 1; 1448 if ((address1 == 0) || (is1Unused)) { 1449 addr1 = 2047; 1450 is1Unused = true; 1451 } 1452 if ((address2 == 0) || (is2Unused)) { 1453 addr2 = 2047; 1454 is2Unused = true; 1455 } 1456 opsw[33] = ((addr1 & 1) == 1); 1457 opsw[34] = ((addr1 & 2) == 2); 1458 opsw[35] = ((addr1 & 4) == 4); 1459 opsw[36] = ((addr1 & 8) == 8); 1460 opsw[37] = ((addr1 & 16) == 16); 1461 opsw[38] = ((addr1 & 32) == 32); 1462 opsw[39] = ((addr1 & 64) == 64); 1463 opsw[40] = false; 1464 opsw[41] = ((addr1 & 128) == 128); 1465 opsw[42] = ((addr1 & 256) == 256); 1466 opsw[43] = ((addr1 & 512) == 512); 1467 opsw[44] = ((addr1 & 1024) == 1024); 1468 opsw[45] = true; 1469 opsw[46] = state1; 1470 if (!is1Unused) { 1471 opsw[47] = false; 1472 opsw[48] = false; 1473 } else { 1474 opsw[47] = true; 1475 opsw[48] = true; 1476 } 1477 1478 opsw[49] = ((addr2 & 1) == 1); 1479 opsw[50] = ((addr2 & 2) == 2); 1480 opsw[51] = ((addr2 & 4) == 4); 1481 opsw[52] = ((addr2 & 8) == 8); 1482 opsw[53] = ((addr2 & 16) == 16); 1483 opsw[54] = ((addr2 & 32) == 32); 1484 opsw[55] = ((addr2 & 64) == 64); 1485 opsw[56] = false; 1486 opsw[57] = ((addr2 & 128) == 128); 1487 opsw[58] = ((addr2 & 256) == 256); 1488 opsw[59] = ((addr2 & 512) == 512); 1489 opsw[60] = ((addr2 & 1024) == 1024); 1490 opsw[61] = true; 1491 opsw[62] = state2; 1492 if (!is2Unused) { 1493 opsw[63] = false; 1494 opsw[64] = false; 1495 } else { 1496 opsw[63] = true; 1497 opsw[64] = true; 1498 } 1499 } 1500 1501 /** 1502 * Updates OpSw values for a given index into the data array 1503 * 1504 * @param index indirect address 1505 */ 1506 protected void updateOpswForWrite(int index) { 1507 Integer value1Address; 1508 Integer value2Address; 1509 boolean value1IsUnused; 1510 boolean value2IsUnused; 1511 boolean value1DirectionIsClosed; 1512 boolean value2DirectionIsClosed; 1513 1514 switch (index) { 1515 case 0: { 1516 try { 1517 value1Address = Integer.parseInt(outAddr1.getText()); 1518 } catch (NumberFormatException e) { 1519 value1Address = 2048; 1520 } 1521 1522 try { 1523 value2Address = Integer.parseInt(outAddr2.getText()); 1524 } catch (NumberFormatException e) { 1525 value2Address = 2048; 1526 } 1527 1528 updateOpSwsOutAddr(value1Address, false, false, value2Address, false, false); 1529 break; 1530 } 1531 case 1: { 1532 try { 1533 value1Address = Integer.parseInt(outAddr3.getText()); 1534 } catch (NumberFormatException e) { 1535 value1Address = 2048; 1536 } 1537 1538 try { 1539 value2Address = Integer.parseInt(outAddr4.getText()); 1540 } catch (NumberFormatException e) { 1541 value2Address = 2048; 1542 } 1543 1544 updateOpSwsOutAddr(value1Address, false, false, value2Address, false, false); 1545 break; 1546 } 1547 case 16: 1548 case 20: 1549 case 24: 1550 case 28: 1551 case 32: 1552 case 36: 1553 case 40: 1554 case 44: { 1555 Integer extractedIndex = (index - 12) / 4; 1556 1557 opsw[47] = false; 1558 opsw[48] = false; // assume valid turnout address entry 1559 opsw[63] = false; 1560 opsw[64] = false; // assume valid turnout address entry 1561 1562 if (routeTop[extractedIndex].getIsUnused()) { 1563 log.warn("updateOpswForWrite - routetop[{}] is unused.", extractedIndex); // NOI18N 1564 value1Address = 2048; 1565 value1IsUnused = true; 1566 value1DirectionIsClosed = true; 1567 } else { 1568 value1DirectionIsClosed = routeTop[extractedIndex].closedRadioButton.isSelected(); 1569 value1IsUnused = false; 1570 try { 1571 value1Address = Integer.parseInt(routeTop[extractedIndex].addressField.getText()); 1572 } catch (NumberFormatException e) { 1573 value1Address = 2048; 1574 value1IsUnused = true; 1575 value1DirectionIsClosed = true; 1576 } 1577 } 1578 1579 if (routeA2[extractedIndex].getIsUnused()) { 1580 log.warn("updateOpswForWrite - routeA2[{}] is unused.", extractedIndex); // NOI18N 1581 value2Address = 2048; 1582 value2IsUnused = true; 1583 value2DirectionIsClosed = true; 1584 } else { 1585 value2DirectionIsClosed = routeA2[extractedIndex].closedRadioButton.isSelected(); 1586 value2IsUnused = false; 1587 try { 1588 value2Address = Integer.parseInt(routeA2[extractedIndex].addressField.getText()); 1589 } catch (NumberFormatException e) { 1590 value2Address = 2048; 1591 value2IsUnused = true; 1592 value2DirectionIsClosed = true; 1593 } 1594 } 1595 1596 updateOpSwsOutAddr(value1Address, value1DirectionIsClosed, value1IsUnused, 1597 value2Address, value2DirectionIsClosed, value2IsUnused); 1598 if (value1IsUnused) { 1599 opsw[46] = true; 1600 opsw[47] = true; 1601 opsw[48] = true; // mark entry as invalid 1602 routeTop[extractedIndex].unusedRadioButton.setSelected(true); 1603 routeTop[extractedIndex].unusedRadioButton.repaint(); 1604 routeTop[extractedIndex].setAddress(2048); 1605 routeTop[extractedIndex].addressField.setText(""); 1606 } 1607 if (value2IsUnused) { 1608 opsw[62] = true; 1609 opsw[63] = true; 1610 opsw[64] = true; // mark entry as invalid 1611 routeA2[extractedIndex].unusedRadioButton.setSelected(true); 1612 routeA2[extractedIndex].unusedRadioButton.repaint(); 1613 routeA2[extractedIndex].setAddress(2048); 1614 routeA2[extractedIndex].addressField.setText(""); 1615 } 1616 break; 1617 } 1618 case 17: 1619 case 21: 1620 case 25: 1621 case 29: 1622 case 33: 1623 case 37: 1624 case 41: 1625 case 45: { 1626 Integer extractedIndex = (index - 13) / 4; 1627 1628 opsw[47] = false; 1629 opsw[48] = false; // assume valid turnout address entry 1630 opsw[63] = false; 1631 opsw[64] = false; // assume valid turnout address entry 1632 1633 if (routeA3[extractedIndex].getIsUnused()) { 1634 value1Address = 2048; 1635 value1IsUnused = true; 1636 value1DirectionIsClosed = true; 1637 } else { 1638 value1DirectionIsClosed = routeA3[extractedIndex].closedRadioButton.isSelected(); 1639 value1IsUnused = false; 1640 try { 1641 value1Address = Integer.parseInt(routeA3[extractedIndex].addressField.getText()); 1642 } catch (NumberFormatException e) { 1643 value1Address = 2048; 1644 value1IsUnused = true; 1645 } 1646 } 1647 1648 if (routeA4[extractedIndex].getIsUnused()) { 1649 value2Address = 2048; 1650 value2IsUnused = true; 1651 value2DirectionIsClosed = true; 1652 } else { 1653 value2DirectionIsClosed = routeA4[extractedIndex].closedRadioButton.isSelected(); 1654 value2IsUnused = false; 1655 try { 1656 value2Address = Integer.parseInt(routeA4[extractedIndex].addressField.getText()); 1657 } catch (NumberFormatException e) { 1658 value2Address = 2048; 1659 value2IsUnused = true; 1660 } 1661 } 1662 1663 updateOpSwsOutAddr(value1Address, value1DirectionIsClosed, value1IsUnused, 1664 value2Address, value2DirectionIsClosed, value2IsUnused); 1665 if (value1IsUnused) { 1666 opsw[46] = true; 1667 opsw[47] = true; 1668 opsw[48] = true; // mark entry as invalid 1669 routeA3[extractedIndex].unusedRadioButton.setSelected(true); 1670 routeA3[extractedIndex].unusedRadioButton.repaint(); 1671 routeA3[extractedIndex].setAddress(2048); 1672 routeA3[extractedIndex].addressField.setText(""); 1673 } 1674 if (value2IsUnused) { 1675 opsw[62] = true; 1676 opsw[63] = true; 1677 opsw[64] = true; // mark entry as invalid 1678 routeA4[extractedIndex].unusedRadioButton.setSelected(true); 1679 routeA4[extractedIndex].unusedRadioButton.repaint(); 1680 routeA4[extractedIndex].setAddress(2048); 1681 routeA4[extractedIndex].addressField.setText(""); 1682 } 1683 break; 1684 } 1685 case 18: 1686 case 22: 1687 case 26: 1688 case 30: 1689 case 34: 1690 case 38: 1691 case 42: 1692 case 46: { 1693 Integer extractedIndex = (index - 14) / 4; 1694 opsw[47] = false; 1695 opsw[48] = false; // assume valid turnout address entry 1696 opsw[63] = false; 1697 opsw[64] = false; // assume valid turnout address entry 1698 1699 if (routeA5[extractedIndex].getIsUnused()) { 1700 value1Address = 2048; 1701 value1IsUnused = true; 1702 value1DirectionIsClosed = true; 1703 } else { 1704 value1DirectionIsClosed = routeA5[extractedIndex].closedRadioButton.isSelected(); 1705 value1IsUnused = false; 1706 try { 1707 value1Address = Integer.parseInt(routeA5[extractedIndex].addressField.getText()); 1708 } catch (NumberFormatException e) { 1709 value1Address = 2048; 1710 value1IsUnused = true; 1711 } 1712 } 1713 1714 if (routeA6[extractedIndex].getIsUnused()) { 1715 value2Address = 2048; 1716 value2IsUnused = true; 1717 value2DirectionIsClosed = true; 1718 } else { 1719 value2DirectionIsClosed = routeA6[extractedIndex].closedRadioButton.isSelected(); 1720 value2IsUnused = false; 1721 try { 1722 value2Address = Integer.parseInt(routeA6[extractedIndex].addressField.getText()); 1723 } catch (NumberFormatException e) { 1724 value2Address = 2048; 1725 value2IsUnused = true; 1726 } 1727 } 1728 1729 updateOpSwsOutAddr(value1Address, value1DirectionIsClosed, value1IsUnused, 1730 value2Address, value2DirectionIsClosed, value2IsUnused); 1731 if (value1IsUnused) { 1732 opsw[46] = true; 1733 opsw[47] = true; 1734 opsw[48] = true; // mark entry as invalid 1735 routeA5[extractedIndex].unusedRadioButton.setSelected(true); 1736 routeA5[extractedIndex].unusedRadioButton.repaint(); 1737 routeA5[extractedIndex].setAddress(2048); 1738 routeA5[extractedIndex].addressField.setText(""); 1739 } 1740 if (value2IsUnused) { 1741 opsw[62] = true; 1742 opsw[63] = true; 1743 opsw[64] = true; // mark entry as invalid 1744 routeA6[extractedIndex].unusedRadioButton.setSelected(true); 1745 routeA6[extractedIndex].unusedRadioButton.repaint(); 1746 routeA6[extractedIndex].setAddress(2048); 1747 routeA6[extractedIndex].addressField.setText(""); 1748 } 1749 break; 1750 } 1751 case 19: 1752 case 23: 1753 case 27: 1754 case 31: 1755 case 35: 1756 case 39: 1757 case 43: 1758 case 47: { 1759 Integer extractedIndex = (index - 15) / 4; 1760 1761 opsw[47] = false; 1762 opsw[48] = false; // assume valid turnout address entry 1763 opsw[63] = false; 1764 opsw[64] = false; // assume valid turnout address entry 1765 1766 if (routeA7[extractedIndex].getIsUnused()) { 1767 value1Address = 2048; 1768 value1IsUnused = true; 1769 value1DirectionIsClosed = true; 1770 } else { 1771 value1DirectionIsClosed = routeA7[extractedIndex].closedRadioButton.isSelected(); 1772 value1IsUnused = false; 1773 try { 1774 value1Address = Integer.parseInt(routeA7[extractedIndex].addressField.getText()); 1775 } catch (NumberFormatException e) { 1776 value1Address = 2048; 1777 value1IsUnused = true; 1778 } 1779 } 1780 1781 if (routeA8[extractedIndex].getIsUnused()) { 1782 value2Address = 2048; 1783 value2IsUnused = true; 1784 value2DirectionIsClosed = true; 1785 } else { 1786 value2DirectionIsClosed = routeA8[extractedIndex].closedRadioButton.isSelected(); 1787 value2IsUnused = false; 1788 try { 1789 value2Address = Integer.parseInt(routeA8[extractedIndex].addressField.getText()); 1790 } catch (NumberFormatException e) { 1791 value2Address = 2048; 1792 value2IsUnused = true; 1793 } 1794 } 1795 1796 updateOpSwsOutAddr(value1Address, value1DirectionIsClosed, value1IsUnused, 1797 value2Address, value2DirectionIsClosed, value2IsUnused); 1798 if (value1IsUnused) { 1799 opsw[46] = true; 1800 opsw[47] = true; 1801 opsw[48] = true; // mark entry as invalid 1802 routeA7[extractedIndex].unusedRadioButton.setSelected(true); 1803 routeA7[extractedIndex].unusedRadioButton.repaint(); 1804 routeA7[extractedIndex].setAddress(2048); 1805 routeA7[extractedIndex].addressField.setText(""); 1806 } 1807 if (value2IsUnused) { 1808 opsw[62] = true; 1809 opsw[63] = true; 1810 opsw[64] = true; // mark entry as invalid 1811 routeA8[extractedIndex].unusedRadioButton.setSelected(true); 1812 routeA8[extractedIndex].unusedRadioButton.repaint(); 1813 routeA8[extractedIndex].setAddress(2048); 1814 routeA8[extractedIndex].addressField.setText(""); 1815 } 1816 break; 1817 } 1818 case 48: { 1819 break; 1820 } 1821 default: { 1822 break; 1823 } 1824 } 1825 } 1826 1827 private void resetRouteOperation(Integer routeNumber) { 1828 if ((routeNumber < 1) || (routeNumber > 8)) { 1829 return; 1830 } 1831 routeTop[routeNumber].unusedRadioButton.setSelected(true); 1832 routeTop[routeNumber].setIsUnused(); 1833 routeTop[routeNumber].addressField.setText(""); 1834 1835 routeA2[routeNumber].setIsUnused(); 1836 routeA2[routeNumber].unusedRadioButton.setSelected(true); 1837 routeA2[routeNumber].addressField.setText(""); 1838 1839 routeA3[routeNumber].setIsUnused(); 1840 routeA3[routeNumber].unusedRadioButton.setSelected(true); 1841 routeA3[routeNumber].addressField.setText(""); 1842 1843 routeA4[routeNumber].setIsUnused(); 1844 routeA4[routeNumber].unusedRadioButton.setSelected(true); 1845 routeA4[routeNumber].addressField.setText(""); 1846 1847 routeA5[routeNumber].setIsUnused(); 1848 routeA5[routeNumber].unusedRadioButton.setSelected(true); 1849 routeA5[routeNumber].addressField.setText(""); 1850 1851 routeA6[routeNumber].setIsUnused(); 1852 routeA6[routeNumber].unusedRadioButton.setSelected(true); 1853 routeA6[routeNumber].addressField.setText(""); 1854 1855 routeA7[routeNumber].setIsUnused(); 1856 routeA7[routeNumber].unusedRadioButton.setSelected(true); 1857 routeA7[routeNumber].addressField.setText(""); 1858 1859 routeA8[routeNumber].setIsUnused(); 1860 routeA8[routeNumber].unusedRadioButton.setSelected(true); 1861 routeA8[routeNumber].addressField.setText(""); 1862 1863 writeAll(); 1864 } 1865 1866 private void unhighlightAllBasicOpSws() { 1867 1868 outputType.setBackground(null); 1869 delayTime.setBackground(null); 1870 outputStates.setBackground(null); 1871 startupDelay.setBackground(null); 1872 staticOutputShutoff.setBackground(null); 1873 commandType.setBackground(null); 1874 routesControl.setBackground(null); 1875 localControlOfOutputsStyle.setBackground(null); 1876 sensorMessageTrigger.setBackground(null); 1877 commandSource.setBackground(null); 1878 output1CrossbuckFlasherCheckBox.setBackground(null); 1879 output2CrossbuckFlasherCheckBox.setBackground(null); 1880 output3CrossbuckFlasherCheckBox.setBackground(null); 1881 output4CrossbuckFlasherCheckBox.setBackground(null); 1882 localSensorType.setBackground(null); 1883 } 1884 1885 private void unhighlightAllRouteEntryFields() { 1886 for (int i = 1; i < 9; ++i) { 1887 routeTop[i].addressField.setBackground(null); 1888 routeA2[i].addressField.setBackground(null); 1889 routeA3[i].addressField.setBackground(null); 1890 routeA4[i].addressField.setBackground(null); 1891 routeA5[i].addressField.setBackground(null); 1892 routeA6[i].addressField.setBackground(null); 1893 routeA7[i].addressField.setBackground(null); 1894 routeA8[i].addressField.setBackground(null); 1895 updateUI(); 1896 } 1897 } 1898 1899 private void unhighlightAllOutputEntryFields() { 1900 outAddr1.setBackground(null); 1901 outAddr2.setBackground(null); 1902 outAddr3.setBackground(null); 1903 outAddr4.setBackground(null); 1904 } 1905 1906 @Override 1907 public void message(LocoNetMessage m) { 1908 super.message(m); 1909 1910 if (m.getOpCode() == LnConstants.OPC_LONG_ACK) { 1911 if (((m.getElement(1) == LnConstants.RE_LACK_SPEC_CASE1) 1912 || (m.getElement(1) == LnConstants.RE_LACK_SPEC_CASE2)) 1913 && (state == 0) && resetRouteButton.isSelected()) { 1914 // Handle DS64 confirmation of OpSw write when action is a DS64 1915 // Board Factory Reset 1916 resetRouteButton.setSelected(false); 1917 resetRouteButton.updateUI(); 1918 } 1919 } 1920 if (m.getOpCode() == LnConstants.OPC_SW_REQ) { 1921 int swAddr = (((m.getElement(2) & 0x0f) * 128) + (m.getElement(1) & 0x7f)) + 1; 1922 boolean dir = ((m.getElement(2) & 0x20) == 0x20); 1923 if (swAddr == Integer.parseInt(outAddr1.getText())) { 1924 outState1.setText(dir ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 1925 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 1926 outState1.updateUI(); 1927 } 1928 if (swAddr == Integer.parseInt(outAddr2.getText())) { 1929 outState2.setText(dir ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 1930 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 1931 outState2.updateUI(); 1932 } 1933 if (swAddr == Integer.parseInt(outAddr3.getText())) { 1934 outState3.setText(dir ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 1935 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 1936 outState3.updateUI(); 1937 } 1938 if (swAddr == Integer.parseInt(outAddr4.getText())) { 1939 outState4.setText(dir ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 1940 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 1941 outState4.updateUI(); 1942 } 1943 } else if ((m.getOpCode() == LnConstants.OPC_MULTI_SENSE) && ((m.getElement(1) & 0x7E) == 0x62)) { 1944 // device identity report 1945 if (m.getElement(3) == 0x03) { 1946 Integer extractedBoardId = 1 + ((m.getElement(1) & 0x1) << 7) 1947 + (m.getElement(2) & 0x7F); 1948 if (!alreadyKnowThisBoardId(extractedBoardId)) { 1949 addBoardIdToList(extractedBoardId); 1950 } 1951 } 1952 } 1953 } 1954 1955 /** 1956 * Reset the DS64 board 1957 */ 1958 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Functionality not yet confirmed with hardware; may be useful at a future date.") 1959 private void boardFactoryReset() { 1960 1961 // before proceeding, make sure that the user really wants to go forward 1962 Object[] dialogBoxButtonOptions = { 1963 Bundle.getMessage("ButtonResetToFactoryDefault"), 1964 Bundle.getMessage("ButtonCancel")}; 1965 int userReply = JmriJOptionPane.showOptionDialog(this, 1966 Bundle.getMessage("DialogTextBoardResetWarning"), 1967 Bundle.getMessage("WarningTitle"), 1968 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, 1969 null, dialogBoxButtonOptions, dialogBoxButtonOptions[1]); 1970 if ( userReply != JmriJOptionPane.YES_OPTION ) { 1971 factoryResetButton.setSelected(false); 1972 return; // compare only to exactly the value for executing the reset! 1973 } 1974 readAllButton.setEnabled(false); 1975 writeAllButton.setEnabled(false); 1976 resetRouteButton.setEnabled(false); 1977 factoryResetButton.setEnabled(false); 1978 1979 // send OpSw 7 = Closed to this boardId to reset the DS64 1980 //to its factory default settings 1981 // then want to read all OpSws to update the display. 1982 read = false; 1983 isWritingResetOpSw = true; 1984 resetOpSwVal = true; 1985 opsw[7] = true; 1986 updateBoardAddress(); 1987 writeOne(7); 1988 boardResetResponseTimer = new javax.swing.Timer(750, 1989 event -> { 1990 factoryResetButton.setSelected(false); 1991 factoryResetButton.setEnabled(true); 1992 readAllButton.setEnabled(true); 1993 writeAllButton.setEnabled(true); 1994 resetRouteButton.setEnabled(true); 1995 updateUI(); 1996 } 1997 ); 1998 boardResetResponseTimer.start(); 1999 } 2000 2001 private final ActionListener routeResetResponseTimerListener = new ActionListener() { 2002 @Override 2003 public void actionPerformed(ActionEvent e) { 2004 log.debug("routeresetresponsetimerlistener state={}, indextoread{}", state, indexToRead); 2005 resetRouteButton.setSelected(false); 2006 readAllButton.setEnabled(true); 2007 writeAllButton.setEnabled(true); 2008 factoryResetButton.setEnabled(true); 2009 } 2010 }; 2011 2012 @Override 2013 public void initComponents(LocoNetSystemConnectionMemo memo) { 2014 super.initComponents(memo); 2015 LocoNetMessage m = new LocoNetMessage(6); 2016 m.setElement(0, LnConstants.OPC_MULTI_SENSE); 2017 m.setElement(1, 0x62); 2018 m.setElement(2, 0); 2019 m.setElement(3, 0x70); 2020 m.setElement(4, 0); 2021 memo.getLnTrafficController().sendLocoNetMessage(m); 2022 } 2023 2024 @Override 2025 public void initComponents() { 2026 super.initComponents(); 2027 // implements an AbstractBoardProgPanel with three tabs: 2028 // Outputs tab - configure features most related to DS64 outputs 2029 // Inputs tab - configure features most related to DS64 inputs 2030 // Routes tab - configure features related to routes 2031 // Routes tab has (left side, vertical) sub-tabs, one for each of the 8 routes 2032 2033 2034// JLabel addrFieldLabel = new JTextLabel(Bundle.getMessage("LabelBoardID")); 2035// addrField = addressComboBox(getSelectedItem); 2036 2037 String[] outputTypes = {Bundle.getMessage("ComboBoxOutputType0"), 2038 Bundle.getMessage("ComboBoxOutputType1")}; 2039 outputTypeLabel = new JLabel(Bundle.getMessage("LabelOutputType")); 2040 outputType = new JComboBox<>(outputTypes); // opSw 1 2041 outputType.setToolTipText(Bundle.getMessage("ToolTipOutputType")); 2042 outputType.addActionListener(basicConfigChangeActionListener); 2043 outputType.setName("1"); // NOI18N 2044 2045 String[] availableDelayTimes = new String[16]; 2046 availableDelayTimes[0] = Bundle.getMessage("ComboBoxPulseTime0point1"); 2047 availableDelayTimes[1] = Bundle.getMessage("ComboBoxPulseTime0point2"); 2048 availableDelayTimes[2] = Bundle.getMessage("ComboBoxPulseTime0point4"); 2049 availableDelayTimes[3] = Bundle.getMessage("ComboBoxPulseTime0point6"); 2050 availableDelayTimes[4] = Bundle.getMessage("ComboBoxPulseTime0point8"); 2051 availableDelayTimes[5] = Bundle.getMessage("ComboBoxPulseTime1point0"); 2052 availableDelayTimes[6] = Bundle.getMessage("ComboBoxPulseTime1point2"); 2053 availableDelayTimes[7] = Bundle.getMessage("ComboBoxPulseTime1point4"); 2054 availableDelayTimes[8] = Bundle.getMessage("ComboBoxPulseTime1point6"); 2055 availableDelayTimes[9] = Bundle.getMessage("ComboBoxPulseTime1point8"); 2056 availableDelayTimes[10] = Bundle.getMessage("ComboBoxPulseTime2point0"); 2057 availableDelayTimes[11] = Bundle.getMessage("ComboBoxPulseTime2point2"); 2058 availableDelayTimes[12] = Bundle.getMessage("ComboBoxPulseTime2point4"); 2059 availableDelayTimes[13] = Bundle.getMessage("ComboBoxPulseTime2point6"); 2060 availableDelayTimes[14] = Bundle.getMessage("ComboBoxPulseTime2point8"); 2061 availableDelayTimes[15] = Bundle.getMessage("ComboBoxPulseTime3point0"); 2062 2063 delayTimeLabel = new JLabel(Bundle.getMessage("LabelPulseTimeout")); // opSws 2-5 2064 delayTime = new JComboBox<>(availableDelayTimes); 2065 delayTime.setToolTipText(Bundle.getMessage("ToolTipPulseTimeout")); 2066 delayTime.setName("2345"); // NOI18N 2067 delayTime.addActionListener(basicConfigChangeActionListener); 2068 2069 String[] initialOutputStates = {Bundle.getMessage("ComboBoxOutputPowerupType0"), 2070 Bundle.getMessage("ComboBoxOutputPowerupType1")}; 2071 outputStatesLabel = new JLabel(Bundle.getMessage("LabelPowerUpOutputActivity")); 2072 outputStates = new JComboBox<>(initialOutputStates); // opsw 6 2073 outputStates.setToolTipText(Bundle.getMessage("ToolTipOutputStates")); 2074 outputStates.setName("6"); // NOI18N 2075 outputStates.addActionListener(basicConfigChangeActionListener); 2076 2077 String[] startupDelays = {Bundle.getMessage("ComboBoxOutputPowerupDelayType0"), 2078 Bundle.getMessage("ComboBoxOutputPowerupDelayType1")}; 2079 startupDelayLabel = new JLabel(Bundle.getMessage("LabelInitialPowerUpDelay")); 2080 startupDelay = new JComboBox<>(startupDelays); // opsw 8 2081 startupDelay.setToolTipText(Bundle.getMessage("ToolTipStartupDelay")); 2082 startupDelay.setName("8"); // NOI18N 2083 startupDelay.addActionListener(basicConfigChangeActionListener); 2084 2085 String[] staticOutputShutoffs = {Bundle.getMessage("ComboBoxOutputPowerManagementType0"), 2086 Bundle.getMessage("ComboBoxOutputPowerManagementType1")}; 2087 staticOutputShutoffLabel = new JLabel(Bundle.getMessage("LabelOutputPowerManagementStyle")); 2088 staticOutputShutoff = new JComboBox<>(staticOutputShutoffs); // opSw 9 2089 staticOutputShutoff.setToolTipText(Bundle.getMessage("ToolTipLabelOutputPowerManagementStyle")); 2090 staticOutputShutoff.setName("9"); // NOI18N 2091 staticOutputShutoff.addActionListener(basicConfigChangeActionListener); 2092 2093 // command sources 2094 String[] commandTypes = {Bundle.getMessage("ComboBoxCommandsRecognizedFromType0"), 2095 Bundle.getMessage("ComboBoxCommandsRecognizedFromType1")}; 2096 commandTypeLabel = new JLabel(Bundle.getMessage("LabelAcceptedSwitchCommandTypes")); 2097 commandType = new JComboBox<>(commandTypes); //opSw 10 2098 commandType.setToolTipText(Bundle.getMessage("ToolTipLabelAcceptedSwitchCommandTypes")); 2099 commandType.setName("10"); // NOI18N 2100 commandType.addActionListener(basicConfigChangeActionListener); 2101 2102 String[] commandSources = {Bundle.getMessage("ComboBoxCommandSourceType0"), 2103 Bundle.getMessage("ComboBoxCommandSourceType1")}; 2104 commandSourceLabel = new JLabel(Bundle.getMessage("LabelAcceptSwitchCommandsFrom")); 2105 commandSource = new JComboBox<>(commandSources); // opSw14 2106 commandSource.setToolTipText(Bundle.getMessage("ToolTipCommandSource")); 2107 commandSource.setName("14"); // NOI18N 2108 commandSource.addActionListener(basicConfigChangeActionListener); 2109 2110 // Crossbuck Flasher controls 2111 output1CrossbuckFlasherCheckBox = new JCheckBox(Bundle.getMessage("CheckBoxOutputXCrossbuck", 1)); 2112 output1CrossbuckFlasherCheckBox.setToolTipText(Bundle.getMessage("ToolTipCheckBoxOutput1Crossbuck")); 2113 output1CrossbuckFlasherCheckBox.setName("17"); // NOI18N 2114 output1CrossbuckFlasherCheckBox.addActionListener(basicConfigChangeActionListener); 2115 // output 2 2116 output2CrossbuckFlasherCheckBox = new JCheckBox(Bundle.getMessage("CheckBoxOutputXCrossbuck", 2)); 2117 output2CrossbuckFlasherCheckBox.setToolTipText(Bundle.getMessage("ToolTipCheckBoxOutput2Crossbuck")); 2118 output2CrossbuckFlasherCheckBox.setName("18"); // NOI18N 2119 output2CrossbuckFlasherCheckBox.addActionListener(basicConfigChangeActionListener); 2120 // output 3 2121 output3CrossbuckFlasherCheckBox = new JCheckBox(Bundle.getMessage("CheckBoxOutputXCrossbuck", 3)); 2122 output3CrossbuckFlasherCheckBox.setToolTipText(Bundle.getMessage("ToolTipCheckBoxOutput3Crossbuck")); 2123 output3CrossbuckFlasherCheckBox.setName("19"); // NOI18N 2124 output3CrossbuckFlasherCheckBox.addActionListener(basicConfigChangeActionListener); 2125 // output 4 2126 output4CrossbuckFlasherCheckBox = new JCheckBox(Bundle.getMessage("CheckBoxOutputXCrossbuck", 4)); 2127 output4CrossbuckFlasherCheckBox.setToolTipText(Bundle.getMessage("ToolTipCheckBoxOutput4Crossbuck")); 2128 output4CrossbuckFlasherCheckBox.setName("20"); // NOI18N 2129 output4CrossbuckFlasherCheckBox.addActionListener(basicConfigChangeActionListener); 2130 2131 // DS64 routes 2132 String[] routesControls = {Bundle.getMessage("ComboBoxEntryRoutesOption0"), 2133 Bundle.getMessage("ComboBoxEntryRoutesOption1"), 2134 Bundle.getMessage("ComboBoxEntryRoutesOption2"), 2135 Bundle.getMessage("ComboBoxEntryRoutesOption3")}; 2136 routesControlLabel = new JLabel(Bundle.getMessage("LabelTriggerDs64Routes")); 2137 routesControl = new JComboBox<>(routesControls); // opSws 11, 16 2138 routesControl.setToolTipText(Bundle.getMessage("ToolTipLabelRouteControlOptions")); 2139 routesControl.setName("1116"); // NOI18N 2140 routesControl.addActionListener(basicConfigChangeActionListener); 2141 2142 // local input controls 2143 String[] localControlOfOutputsStyles = { 2144 Bundle.getMessage("ComboBoxInputsControlOutputsType0"), 2145 Bundle.getMessage("ComboBoxInputsControlOutputsType1"), 2146 Bundle.getMessage("ComboBoxInputsControlOutputsType2"), 2147 Bundle.getMessage("comboboxInputsControlOutputsType3")}; 2148 localControlOfOutputsStyleLabel = new JLabel(Bundle.getMessage("LabelLocalInputsControlOutputs")); 2149 localControlOfOutputsStyle = new JComboBox<>(localControlOfOutputsStyles); // opSw12 2150 localControlOfOutputsStyle.setToolTipText(Bundle.getMessage("ToolTipLocalInputsControl")); 2151 localControlOfOutputsStyle.setName("1215"); // NOI18N 2152 localControlOfOutputsStyle.addActionListener(basicConfigChangeActionListener); 2153 2154 String[] sensorMessageTriggers = {Bundle.getMessage("ComboBoxInputsCauseMessagesType0"), 2155 Bundle.getMessage("ComboBoxInputsCauseMessagesType1")}; 2156 sensorMessageTriggerLabel = new JLabel(Bundle.getMessage("LabelBetweenForMessageTypeSent")); 2157 sensorMessageTrigger = new JComboBox<>(sensorMessageTriggers); // opSw13 2158 sensorMessageTrigger.setToolTipText(Bundle.getMessage("ToolTipSensorMessageTrigger")); 2159 sensorMessageTrigger.setName("13"); // NOI18N 2160 sensorMessageTrigger.addActionListener(basicConfigChangeActionListener); 2161 2162 String[] localSensorTypes = {Bundle.getMessage("ComboBoxSensorMessageTypeSentType0"), 2163 Bundle.getMessage("ComboBoxSensorMessageTypeSentType1")}; 2164 localSensorType = new JComboBox<>(localSensorTypes); // opSw21 2165 localSensorType.setToolTipText(Bundle.getMessage("ToolTipLocalSensorsType")); 2166 localSensorType.setName("21"); // NOI18N 2167 localSensorType.addActionListener(basicConfigChangeActionListener); 2168 2169 factoryResetButton = new JToggleButton(Bundle.getMessage("ButtonResetToFactoryDefault")); 2170 factoryResetButton.setToolTipText(Bundle.getMessage("ToolTipButtonResetToFactoryDefault")); 2171 factoryResetButton.addActionListener( 2172 event -> { 2173 readAllButton.setEnabled(false); 2174 writeAllButton.setEnabled(false); 2175 resetRouteButton.setEnabled(false); 2176 boardFactoryReset(); 2177 } 2178 ); 2179 routesTabbedPane = new JTabbedPane(); 2180 2181 routePanel = new JPanel[9]; 2182 routeTop = new SimpleTurnoutStateEntry[9]; 2183 routeA2 = new SimpleTurnoutStateEntry[9]; 2184 routeA3 = new SimpleTurnoutStateEntry[9]; 2185 routeA4 = new SimpleTurnoutStateEntry[9]; 2186 routeA5 = new SimpleTurnoutStateEntry[9]; 2187 routeA6 = new SimpleTurnoutStateEntry[9]; 2188 routeA7 = new SimpleTurnoutStateEntry[9]; 2189 routeA8 = new SimpleTurnoutStateEntry[9]; 2190 2191 resetRouteButton = new JToggleButton(Bundle.getMessage("ButtonResetRoute")); 2192 resetRouteButton.setToolTipText(Bundle.getMessage("ToolTipButtonResetRoute")); 2193 resetRouteButton.setEnabled(false); 2194 resetRouteButton.setVisible(false); 2195 2196 JPanel addressingPanel = provideAddressing(" "); // create read/write buttons, address 2197 readAllButton.setPreferredSize(null); 2198 readAllButton.setText(Bundle.getMessage("ButtonReadFullSheet")); 2199 readAllButton.setToolTipText(Bundle.getMessage("ToolTipButtonReadFullSheet")); 2200 2201 writeAllButton.setPreferredSize(null); 2202 writeAllButton.setText(Bundle.getMessage("ButtonWriteFullSheet")); 2203 writeAllButton.setToolTipText(Bundle.getMessage("ToolTipButtonWriteFullSheet")); 2204 2205 // make both buttons a little bit bigger, with identical (preferred) sizes 2206 // (width increased because some computers/displays trim the button text) 2207 java.awt.Dimension d = writeAllButton.getPreferredSize(); 2208 int w = d.width; 2209 d = readAllButton.getPreferredSize(); 2210 if (d.width > w) { 2211 w = d.width; 2212 } 2213 writeAllButton.setPreferredSize(new java.awt.Dimension((int) (w * 1.1), d.height)); 2214 readAllButton.setPreferredSize(new java.awt.Dimension((int) (w * 1.1), d.height)); 2215 2216 addressingPanel.add(resetRouteButton); 2217 int indexOfTargetBoardAddress = 0; 2218 2219 addressComboBox = new JComboBox<>(); 2220 for (Integer index = 0; index < boardNumsEntryValue.size(); ++index) { 2221 if (boardNumsEntryValue.get(index) == origAccessBoardNum) { 2222 origAccessBoardNum = -1; 2223 indexOfTargetBoardAddress = index; 2224 } 2225 addressComboBox.addItem(boardNumsEntryValue.get(index)); 2226 } 2227 2228 addressComboBox.setSelectedIndex(indexOfTargetBoardAddress); 2229 addressingPanel.add(addressComboBox, 1); 2230 addressingPanel.getComponent(2).setVisible(false); 2231 addressComboBox.setEditable(true); 2232 2233 appendLine(addressingPanel); // add read/write buttons, address 2234 2235 generalTabbedPane = new JTabbedPane(); 2236 generalPanel = new JPanel(); 2237 generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS)); 2238 generalPanel.setName("Basic Settings"); // NOI18N 2239 2240 JPanel allOutputControls = new JPanel(); 2241 allOutputControls.setLayout(new BoxLayout(allOutputControls, BoxLayout.Y_AXIS)); 2242 javax.swing.border.TitledBorder allOutputControlsTitleBorder; 2243 javax.swing.border.Border blackline; 2244 blackline = javax.swing.BorderFactory.createLineBorder(java.awt.Color.black); 2245 allOutputControlsTitleBorder = javax.swing.BorderFactory.createTitledBorder(blackline, 2246 Bundle.getMessage("TitledBorderLabelOutputControls")); 2247 allOutputControls.setBorder(allOutputControlsTitleBorder); 2248 2249 JPanel outputTypePanel = new JPanel(); 2250 outputTypePanel.setLayout(new FlowLayout()); 2251 outputTypePanel.add(outputTypeLabel); 2252 outputTypePanel.add(outputType); 2253 allOutputControls.add(outputTypePanel); 2254 2255 JPanel delayTimePanel = new JPanel(); 2256 delayTimePanel.setLayout(new FlowLayout()); 2257 delayTimePanel.add(delayTimeLabel); 2258 delayTimePanel.add(delayTime); 2259 allOutputControls.add(delayTimePanel); 2260 2261 JPanel outputStatePanel = new JPanel(); 2262 outputStatePanel.setLayout(new FlowLayout()); 2263 outputStatePanel.add(outputStatesLabel); 2264 outputStatePanel.add(outputStates); 2265 allOutputControls.add(outputStatePanel); 2266 2267 JPanel startupDelayPanel = new JPanel(); 2268 startupDelayPanel.setLayout(new FlowLayout()); 2269 startupDelayPanel.add(startupDelayLabel); 2270 startupDelayPanel.add(startupDelay); 2271 allOutputControls.add(startupDelayPanel); 2272 2273 JPanel staticOutputShutoffPanel = new JPanel(); 2274 staticOutputShutoffPanel.setLayout(new FlowLayout()); 2275 staticOutputShutoffPanel.add(staticOutputShutoffLabel); 2276 staticOutputShutoffPanel.add(staticOutputShutoff); 2277 allOutputControls.add(staticOutputShutoffPanel); 2278 2279 JPanel crossingGateControls = new JPanel(new java.awt.GridLayout(2, 2)); 2280 crossingGateControls.add(output1CrossbuckFlasherCheckBox); 2281 crossingGateControls.add(output3CrossbuckFlasherCheckBox); // display output 3 box to the right of output 1 box 2282 crossingGateControls.add(output2CrossbuckFlasherCheckBox); // display output 2 box below output 1 box 2283 crossingGateControls.add(output4CrossbuckFlasherCheckBox); 2284 allOutputControls.add(crossingGateControls); 2285 2286 generalPanel.add(allOutputControls); 2287 2288 // command sources 2289 JPanel ds64CommandSourcesPanel = new JPanel(); 2290 ds64CommandSourcesPanel.setLayout(new BoxLayout(ds64CommandSourcesPanel, BoxLayout.Y_AXIS)); 2291 javax.swing.border.TitledBorder ds64CommandSourcesTitleBorder; 2292 ds64CommandSourcesTitleBorder = javax.swing.BorderFactory.createTitledBorder(blackline, 2293 Bundle.getMessage("TitledBorderLabelCommandSources")); 2294 ds64CommandSourcesPanel.setBorder(ds64CommandSourcesTitleBorder); 2295 2296 JPanel commandTypePanel = new JPanel(); 2297 commandTypePanel.setLayout(new FlowLayout()); 2298 commandTypePanel.add(commandTypeLabel); 2299 commandTypePanel.add(commandType); 2300 ds64CommandSourcesPanel.add(commandTypePanel); 2301 2302 JPanel commandSourcePanel = new JPanel(); 2303 commandSourcePanel.setLayout(new FlowLayout()); 2304 commandSourcePanel.add(commandSourceLabel); 2305 commandSourcePanel.add(commandSource); 2306 ds64CommandSourcesPanel.add(commandSourcePanel); 2307 2308 generalPanel.add(ds64CommandSourcesPanel); 2309 2310 // DS64 routes 2311 JPanel localRoutesPanel = new JPanel(); 2312 localRoutesPanel.setLayout(new BoxLayout(localRoutesPanel, BoxLayout.Y_AXIS)); 2313 javax.swing.border.TitledBorder localRoutesTitleBorder; 2314 localRoutesTitleBorder = javax.swing.BorderFactory.createTitledBorder(blackline, 2315 Bundle.getMessage("TitledBorderLabelRoutes")); 2316 localRoutesPanel.setBorder(localRoutesTitleBorder); 2317 2318 JPanel routesControlPanel = new JPanel(); 2319 routesControlPanel.setLayout(new FlowLayout()); 2320 routesControlPanel.add(routesControlLabel); 2321 routesControlPanel.add(routesControl); 2322 localRoutesPanel.add(routesControlPanel); 2323 2324 generalPanel.add(localRoutesPanel); 2325 2326 // local input controls 2327 localInputControlsPanel = new JPanel(); 2328 localInputControlsPanel.setLayout(new BoxLayout(localInputControlsPanel, BoxLayout.Y_AXIS)); 2329 javax.swing.border.TitledBorder localInputControlsTitleBorder; 2330 localInputControlsTitleBorder = javax.swing.BorderFactory.createTitledBorder(blackline, 2331 Bundle.getMessage("TitledBorderLabelLocalInputControls")); 2332 localInputControlsPanel.setBorder(localInputControlsTitleBorder); 2333 2334 JPanel localControlOfOutputsStylePanel = new JPanel(new FlowLayout()); 2335 localControlOfOutputsStylePanel.add(localControlOfOutputsStyleLabel); 2336 localControlOfOutputsStylePanel.add(localControlOfOutputsStyle); 2337 localInputControlsPanel.add(localControlOfOutputsStylePanel); 2338 2339 sensorMessageTriggerPanel = new JPanel(new FlowLayout()); 2340 sensorMessageTriggerPanel.add(localSensorType); 2341 sensorMessageTriggerPanel.add(sensorMessageTriggerLabel); 2342 sensorMessageTriggerPanel.add(sensorMessageTrigger); 2343 localInputControlsPanel.add(sensorMessageTriggerPanel); 2344 2345 generalPanel.add(localInputControlsPanel); 2346 2347 generalPanel.add(new JSeparator()); 2348 JPanel factoryResetButtonPanel = new JPanel(); 2349 factoryResetButtonPanel.add(factoryResetButton); 2350 generalPanel.add(factoryResetButtonPanel); 2351 2352 generalTabbedPane.addTab(Bundle.getMessage("TabTextBasicSettings"), null, 2353 generalPanel, Bundle.getMessage("TabToolTipBasicSettings")); 2354 2355 // opsws panel 2356 opswsPanel = new JPanel(); 2357 2358 opswsValues = new JPanel(); 2359 opswsValues.setLayout(new BoxLayout(opswsValues, BoxLayout.Y_AXIS)); 2360 javax.swing.border.TitledBorder opswsValuesTitleBorder; 2361 opswsValuesTitleBorder = javax.swing.BorderFactory.createTitledBorder(blackline, 2362 Bundle.getMessage("TitledBorderLabelOpSws")); 2363 opswsValues.setBorder(opswsValuesTitleBorder); 2364 2365 opswsPanel.setLayout(new BoxLayout(opswsPanel, BoxLayout.Y_AXIS)); 2366 JPanel innerPanel; 2367 ButtonGroup[] g = new ButtonGroup[22]; 2368 opswThrown = new JRadioButtonWithInteger[22]; 2369 opswClosed = new JRadioButtonWithInteger[22]; 2370 for (int i = 1; i <= 21; i++) { 2371 if (i != 7) { 2372 log.debug("Creating entry for OpSw {}", i); 2373 innerPanel = new JPanel(new FlowLayout()); 2374 innerPanel.add(new JLabel("OpSw " + i)); // NOI18N 2375 opswThrown[i] = new JRadioButtonWithInteger(i, Bundle.getMessage("TurnoutStateThrown")); 2376 opswClosed[i] = new JRadioButtonWithInteger(i, Bundle.getMessage("TurnoutStateClosed")); 2377 g[i] = new ButtonGroup(); 2378 g[i].add(opswThrown[i]); 2379 g[i].add(opswClosed[i]); 2380 innerPanel.add(opswThrown[i]); 2381 innerPanel.add(opswClosed[i]); 2382 opswsPanel.add(innerPanel); 2383// opswsPanel.add(new JSeparator()); 2384 opswThrown[i].addItemListener(event -> { 2385 if (event.getSource().getClass() == JRadioButtonWithInteger.class) { 2386 JRadioButtonWithInteger source = ((JRadioButtonWithInteger) (event.getSource())); 2387 int ind = source.index; 2388 boolean st = (event.getStateChange() == ItemEvent.DESELECTED); 2389 log.debug("ItemEventListener Opsw values: {} thrown radio button event: {} {}.", ind, st, st ? "Closed" : "Thrown"); // NOI18N 2390 opsw[ind] = st; 2391 copyOpswToBasic(); 2392 } 2393 }); 2394 } 2395 } 2396 opswsValues.add(opswsPanel); 2397 opswsScrollPane = new JScrollPane(opswsValues); 2398 opswsScrollPane.setPreferredSize(new java.awt.Dimension(180, 200)); 2399 opswsScrollPane.setName("Simple OpSws"); // NOI18N 2400 2401 generalTabbedPane.addTab(Bundle.getMessage("TabTextOpSwValues"), null, 2402 opswsScrollPane, Bundle.getMessage("TabToolTipOpSwValues")); 2403 2404 outputAddrsPanel = new JPanel(); 2405 outputAddrsPanel.setLayout(new BoxLayout(outputAddrsPanel, BoxLayout.Y_AXIS)); 2406 2407 JPanel p = new JPanel(); 2408 2409 p.setLayout(new FlowLayout()); 2410 p.add(new JLabel(Bundle.getMessage("LabelCautionReadingWritingCanCauseOutputChanges"))); 2411 outputAddrsPanel.add(p); 2412 2413 p = new JPanel(); 2414 p.setLayout(new FlowLayout()); 2415 p.add(new JLabel(Bundle.getMessage("LabelTextOutputX", 1))); 2416 outAddr1 = new ValidatedTextField(5, false, 1, 2048, Bundle.getMessage("ErrorTextNonBlankAddressInvalid")); 2417 outState1 = new JLabel(Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateUnknown"))); 2418 p.add(outAddr1); 2419 p.add(outState1); 2420 outputAddrsPanel.add(p); 2421 2422 p = new JPanel(); 2423 p.setLayout(new FlowLayout()); 2424 p.add(new JLabel(Bundle.getMessage("LabelTextOutputX", 2))); 2425 outAddr2 = new ValidatedTextField(5, false, 1, 2048, Bundle.getMessage("ErrorTextNonBlankAddressInvalid")); 2426 outState2 = new JLabel(Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateUnknown"))); 2427 p.add(outAddr2); 2428 p.add(outState2); 2429 outputAddrsPanel.add(p); 2430 2431 p = new JPanel(); 2432 p.setLayout(new FlowLayout()); 2433 p.add(new JLabel(Bundle.getMessage("LabelTextOutputX", 3))); 2434 outAddr3 = new ValidatedTextField(5, false, 1, 2048, Bundle.getMessage("ErrorTextNonBlankAddressInvalid")); 2435 outState3 = new JLabel(Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateUnknown"))); 2436 p.add(outAddr3); 2437 p.add(outState3); 2438 outputAddrsPanel.add(p); 2439 2440 p = new JPanel(); 2441 p.setLayout(new FlowLayout()); 2442 p.add(new JLabel(Bundle.getMessage("LabelTextOutputX", 4))); 2443 outAddr4 = new ValidatedTextField(5, false, 1, 2048, Bundle.getMessage("ErrorTextNonBlankAddressInvalid")); 2444 outState4 = new JLabel(Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateUnknown"))); 2445 p.add(outAddr4); 2446 p.add(outState4); 2447 outputAddrsPanel.add(p); 2448 outputAddrsPanel.add(new JSeparator()); 2449 2450 p = new JPanel(); 2451 p.setLayout(new FlowLayout()); 2452 p.add(new JLabel(Bundle.getMessage("LabelOutputsTabSensorNotes"))); 2453 outputAddrsPanel.add(p); 2454 2455 generalTabbedPane.addTab(Bundle.getMessage("TabTextOutputAddrs"), null, 2456 outputAddrsPanel, Bundle.getMessage("TabToolTipOutputAddrs")); 2457 2458 routePanel[0] = new JPanel(); 2459 2460 routesTabbedPane.setTabPlacement(JTabbedPane.LEFT); 2461 // create route panels (one tab each for each of 8 routes) 2462 for (int i = 1; i <= 8; ++i) { 2463 routePanel[i] = new JPanel(); 2464 routePanel[i].setLayout(new BoxLayout(routePanel[i], BoxLayout.Y_AXIS)); 2465 2466 routePanel[i].add(new JLabel(Bundle.getMessage("TabTextSpecificRoute", 2467 Integer.toString(i)))); 2468 routePanel[i].add(new JSeparator()); 2469 JPanel q = new JPanel(new FlowLayout()); 2470 q.add(new JLabel(Bundle.getMessage("LabelCautionReadingWritingCanCauseOutputChanges"))); 2471 routePanel[i].add(q); 2472 routePanel[i].add(new JSeparator()); 2473 routeTop[i] = new SimpleTurnoutStateEntry(2048, false, true); 2474 routeA2[i] = new SimpleTurnoutStateEntry(2048, false, true); 2475 routeA3[i] = new SimpleTurnoutStateEntry(2048, false, true); 2476 routeA4[i] = new SimpleTurnoutStateEntry(2048, false, true); 2477 routeA5[i] = new SimpleTurnoutStateEntry(2048, false, true); 2478 routeA6[i] = new SimpleTurnoutStateEntry(2048, false, true); 2479 routeA7[i] = new SimpleTurnoutStateEntry(2048, false, true); 2480 routeA8[i] = new SimpleTurnoutStateEntry(2048, false, true); 2481 2482 routePanel[i].add(routeTop[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 2483 Bundle.getMessage("LabelTextRouteXTopTurnout")))); 2484 routePanel[i].add(routeA2[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 2))); 2485 routePanel[i].add(routeA3[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 3))); 2486 routePanel[i].add(routeA4[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 4))); 2487 routePanel[i].add(routeA5[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 5))); 2488 routePanel[i].add(routeA6[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 6))); 2489 routePanel[i].add(routeA7[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 7))); 2490 routePanel[i].add(routeA8[i].createEntryPanel(Bundle.getMessage("LabelTextRouteXSpecificTurnout", 8))); 2491 2492 routesTabbedPane.addTab( 2493 Bundle.getMessage("TabTextSpecificRoute", Integer.toString(i)), 2494 null, 2495 routePanel[i], 2496 Bundle.getMessage("TabToolTipSpecificRoute", Integer.toString(i)) 2497 ); 2498 } 2499 2500 generalTabbedPane.addTab(Bundle.getMessage("TabTextRoutes"), 2501 null, routesTabbedPane, 2502 Bundle.getMessage("ToolTipTabTextRoutes")); 2503 resetRouteButton.addActionListener( 2504 event -> { 2505 readAllButton.setEnabled(false); 2506 writeAllButton.setEnabled(false); 2507 factoryResetButton.setEnabled(false); 2508 2509 Integer routeNumber = 0; 2510 if (((JTabbedPane) generalTabbedPane.getSelectedComponent()) != routesTabbedPane) { 2511 return; 2512 } 2513 if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[1]) { 2514 routeNumber = 1; 2515 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[2]) { 2516 routeNumber = 2; 2517 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[3]) { 2518 routeNumber = 3; 2519 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[4]) { 2520 routeNumber = 4; 2521 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[5]) { 2522 routeNumber = 5; 2523 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[6]) { 2524 routeNumber = 6; 2525 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[7]) { 2526 routeNumber = 7; 2527 } else if (((JPanel) routesTabbedPane.getSelectedComponent()) == routePanel[8]) { 2528 routeNumber = 8; 2529 } 2530 if (routeNumber != 0) { 2531 // before proceeding, make sure that the user really wants to go forward 2532 Object[] dialogBoxButtonOptions = { 2533 Bundle.getMessage("ButtonResetRouteN", routeNumber), 2534 Bundle.getMessage("ButtonCancel")}; 2535 int userReply = JmriJOptionPane.showOptionDialog(this, 2536 Bundle.getMessage("DialogTextClearRouteWarning", routeNumber), 2537 Bundle.getMessage("WarningTitle"), 2538 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE, 2539 null, dialogBoxButtonOptions, dialogBoxButtonOptions[1]); 2540 if ( userReply != JmriJOptionPane.YES_OPTION ) { 2541 resetRouteButton.setSelected(false); 2542 return; // compare only to exactly the value for executing the "clear route" operation! 2543 } 2544 2545 resetRouteOperation(routeNumber); 2546 } 2547 readAllButton.setEnabled(true); 2548 writeAllButton.setEnabled(true); 2549 factoryResetButton.setEnabled(true); 2550 resetRouteButton.setSelected(false); 2551 } 2552 ); 2553 2554 appendLine(generalTabbedPane); 2555 JPanel statusPanel = new JPanel(); 2556 setStatus(" "); 2557 statusPanel.add(new JSeparator()); 2558 statusPanel.add(provideStatusLine()); 2559 statusPanel.add(new JSeparator()); 2560 appendLine(statusPanel); 2561 2562 setTypeWord(0x73); // configure DS64 message type 2563 opsw[7] = false; 2564 operationType = OpSwOpType.BasicsRead; 2565 2566 routesTabbedPane.addChangeListener(new ChangeListener() { 2567 // This method is called whenever the selected tab changes 2568 2569 String route1TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(1)); 2570 String route2TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(2)); 2571 String route3TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(3)); 2572 String route4TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(4)); 2573 String route5TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(5)); 2574 String route6TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(6)); 2575 String route7TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(7)); 2576 String route8TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(8)); 2577 2578 @Override 2579 public void stateChanged(ChangeEvent evt) { 2580 unhighlightAllBasicOpSws(); 2581 unhighlightAllOutputEntryFields(); 2582 unhighlightAllRouteEntryFields(); 2583 2584 String activeTabTitle = routesTabbedPane.getTitleAt(routesTabbedPane.getSelectedIndex()); 2585 2586 if ((activeTabTitle.equals(route1TabText)) 2587 || (activeTabTitle.equals(route2TabText)) 2588 || (activeTabTitle.equals(route3TabText)) 2589 || (activeTabTitle.equals(route4TabText)) 2590 || (activeTabTitle.equals(route5TabText)) 2591 || (activeTabTitle.equals(route6TabText)) 2592 || (activeTabTitle.equals(route7TabText)) 2593 || (activeTabTitle.equals(route8TabText))) { 2594 resetRouteButton.setVisible(true); 2595 resetRouteButton.setEnabled(true); 2596 resetRouteButton.updateUI(); 2597 readAllButton.setSelected(false); 2598 readAllButton.updateUI(); 2599 updateUI(); 2600 } 2601 } 2602 2603 }); 2604 2605 generalTabbedPane.addChangeListener(new ChangeListener() { 2606 // This method is called whenever the selected tab changes 2607 String route1TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(1)); 2608 String route2TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(2)); 2609 String route3TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(3)); 2610 String route4TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(4)); 2611 String route5TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(5)); 2612 String route6TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(6)); 2613 String route7TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(7)); 2614 String route8TabText = Bundle.getMessage("TabTextSpecificRoute", Integer.toString(8)); 2615 String outputsTabText = Bundle.getMessage("TabTextOutputAddrs"); 2616 2617 @Override 2618 public void stateChanged(ChangeEvent evt) { 2619 String activeTabTitle; 2620 unhighlightAllBasicOpSws(); 2621 unhighlightAllOutputEntryFields(); 2622 unhighlightAllRouteEntryFields(); 2623 2624 activeTabTitle = generalTabbedPane.getTitleAt(generalTabbedPane.getSelectedIndex()); 2625 JTabbedPane pane = (JTabbedPane) evt.getSource(); 2626 2627 // Get current tab 2628 if ((activeTabTitle.equals(Bundle.getMessage("TabTextRoutes")))) { 2629 activeTabTitle = routesTabbedPane.getTitleAt(routesTabbedPane.getSelectedIndex()); 2630 if ((activeTabTitle.equals(route1TabText)) 2631 || (activeTabTitle.equals(route2TabText)) 2632 || (activeTabTitle.equals(route3TabText)) 2633 || (activeTabTitle.equals(route4TabText)) 2634 || (activeTabTitle.equals(route5TabText)) 2635 || (activeTabTitle.equals(route6TabText)) 2636 || (activeTabTitle.equals(route7TabText)) 2637 || (activeTabTitle.equals(route8TabText))) { 2638 resetRouteButton.setEnabled(true); 2639 resetRouteButton.setVisible(true); 2640 readAllButton.setEnabled(true); 2641 writeAllButton.setSelected(false); 2642 readAllButton.setSelected(false); 2643 writeAllButton.setEnabled(true); 2644 factoryResetButton.setEnabled(true); 2645 routesTabbedPane.updateUI(); 2646 updateUI(); 2647 } else { 2648 routesTabbedPane.setSelectedIndex(0); 2649 routesTabbedPane.updateUI(); 2650 } 2651 } else if (activeTabTitle.equals(outputsTabText)) { 2652 resetRouteButton.setEnabled(false); 2653 resetRouteButton.setVisible(false); 2654 readAllButton.setEnabled(true); 2655 writeAllButton.setSelected(false); 2656 readAllButton.setSelected(false); 2657 writeAllButton.setEnabled(true); 2658 readAllButton.updateUI(); 2659 updateUI(); 2660 } else { 2661 readAllButton.setEnabled(true); 2662 writeAllButton.setEnabled(true); 2663 writeAllButton.setSelected(false); 2664 readAllButton.setSelected(false); 2665 resetRouteButton.setVisible(false); 2666 resetRouteButton.setEnabled(false); 2667 readAllButton.updateUI(); 2668 updateUI(); 2669 } 2670 Container c = pane.getRootPane().getParent(); 2671 c.setPreferredSize(null); 2672 if (c instanceof Window) { 2673 ((Window) c).pack(); 2674 } 2675 } 2676 2677 }); 2678 2679 responseTimer.addActionListener(routeResetResponseTimerListener); 2680 commandType.setToolTipText(Bundle.getMessage("ToolTipLabelAcceptedSwitchCommandTypes")); 2681 updateBasicOpSwTab(); 2682 2683 panelToScroll(); 2684 2685 } 2686 2687 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "Cannot catch an exception without grabbing the exception, but we don't do anything with the exception details.") 2688 private void updateGuiFromOpSws49_64() { 2689 Integer readValue; 2690 boolean isUsed = true; 2691 2692 readValue = 0; 2693 for (int i = 60; i >= 49; i--) { 2694 if (i != 56) { 2695 readValue = (readValue << 1) + (opsw[i] ? 1 : 0); 2696 } 2697 } 2698 readValue++; // account for physical/user numbering difference 2699 2700 String readValueString = readValue.toString(); 2701 if ((opsw[63] == true) && (opsw[64] == true)) { 2702 readValueString = ""; 2703 isUsed = false; 2704 } 2705 boolean direction = opsw[62]; 2706 2707 switch (indexToRead) { 2708 case 0: { 2709 // have read value for output2 - update local storage 2710 outAddr2.setText(Integer.toString(readValue)); 2711 outAddr2.setLastQueriedValue(outAddr2.getText()); 2712 outState2.setText(direction 2713 ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 2714 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 2715 break; 2716 } 2717 case 1: { 2718 // have read value for output4 - update local storage 2719 outAddr4.setText(Integer.toString(readValue)); 2720 outAddr4.setLastQueriedValue(outAddr4.getText()); 2721 outState4.setText(direction 2722 ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 2723 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 2724 break; 2725 } 2726 case 16: 2727 case 20: 2728 case 24: 2729 case 28: 2730 case 32: 2731 case 36: 2732 case 40: 2733 case 44: { 2734 // have a read value for Route n - update local storage 2735 Integer effectiveIndex = (indexToRead - 12) / 4; 2736 2737 if (isUsed == false) { 2738 routeA2[effectiveIndex].setIsUnused(); 2739 routeA2[effectiveIndex].addressField.setText(""); 2740 routeA2[effectiveIndex].unusedRadioButton.setSelected(true); 2741 } else { 2742 routeA2[effectiveIndex].setAddress(readValue); 2743 routeA2[effectiveIndex].addressField.setText(readValueString); 2744 routeA2[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2745 if (opsw[62] == true) { 2746 routeA2[effectiveIndex].closedRadioButton.setSelected(true); 2747 } else { 2748 routeA2[effectiveIndex].thrownRadioButton.setSelected(true); 2749 } 2750 } 2751 break; 2752 } 2753 case 17: 2754 case 21: 2755 case 25: 2756 case 29: 2757 case 33: 2758 case 37: 2759 case 41: 2760 case 45: { 2761 // have a read value for Route n - update local storage 2762 Integer effectiveIndex = (indexToRead - 13) / 4; 2763 if (isUsed == false) { 2764 routeA4[effectiveIndex].setIsUnused(); 2765 routeA4[effectiveIndex].addressField.setText(""); 2766 routeA4[effectiveIndex].unusedRadioButton.setSelected(true); 2767 } else { 2768 routeA4[effectiveIndex].setAddress(readValue); 2769 routeA4[effectiveIndex].addressField.setText(readValueString); 2770 routeA4[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2771 if (opsw[62] == true) { 2772 routeA4[effectiveIndex].closedRadioButton.setSelected(true); 2773 } else { 2774 routeA4[effectiveIndex].thrownRadioButton.setSelected(true); 2775 } 2776 } 2777 break; 2778 } 2779 case 18: 2780 case 22: 2781 case 26: 2782 case 30: 2783 case 34: 2784 case 38: 2785 case 42: 2786 case 46: { 2787 // have a read value for Route n - update local storage 2788 Integer effectiveIndex = (indexToRead - 14) / 4; 2789 if (isUsed == false) { 2790 routeA6[effectiveIndex].setIsUnused(); 2791 routeA6[effectiveIndex].addressField.setText(""); 2792 routeA6[effectiveIndex].unusedRadioButton.setSelected(true); 2793 } else { 2794 routeA6[effectiveIndex].setAddress(readValue); 2795 routeA6[effectiveIndex].addressField.setText(readValueString); 2796 routeA6[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2797 if (opsw[62] == true) { 2798 routeA6[effectiveIndex].closedRadioButton.setSelected(true); 2799 } else { 2800 routeA6[effectiveIndex].thrownRadioButton.setSelected(true); 2801 } 2802 } 2803 break; 2804 } 2805 case 19: 2806 case 23: 2807 case 27: 2808 case 31: 2809 case 35: 2810 case 39: 2811 case 43: 2812 case 47: { 2813 // have a read value for Route n - update local storage 2814 Integer effectiveIndex = (indexToRead - 15) / 4; 2815 if (isUsed == false) { 2816 routeA8[effectiveIndex].setIsUnused(); 2817 routeA8[effectiveIndex].addressField.setText(""); 2818 routeA8[effectiveIndex].unusedRadioButton.setSelected(true); 2819 } else { 2820 routeA8[effectiveIndex].setAddress(readValue); 2821 routeA8[effectiveIndex].addressField.setText(readValueString); 2822 routeA8[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2823 if (opsw[62] == true) { 2824 routeA8[effectiveIndex].closedRadioButton.setSelected(true); 2825 } else { 2826 routeA8[effectiveIndex].thrownRadioButton.setSelected(true); 2827 } 2828 } 2829 break; 2830 } 2831 default: 2832 break; 2833 } 2834 } 2835 2836 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "Cannot catch an exception without grabbing the exception, but we don't do anything with the exception details.") 2837 void updateGuiFromOpSws33_48() { 2838 Integer readValue; 2839 boolean isUsed = true; 2840 2841 readValue = 0; 2842 for (int i = 44; i >= 33; i--) { 2843 if (i != 40) { 2844 readValue = (readValue << 1) + (opsw[i] ? 1 : 0); 2845 } 2846 } 2847 readValue++; // account for physical/user numbering difference 2848 2849 String readValueString = readValue.toString(); 2850 if ((opsw[47] == true) && (opsw[48] == true)) { 2851 readValueString = ""; 2852 isUsed = false; 2853 } 2854 boolean direction = opsw[46]; 2855 2856 switch (indexToRead) { 2857 case 0: { 2858 // have read value for output1 - update local storage 2859 outAddr1.setText(readValueString); 2860 outAddr1.setLastQueriedValue(readValueString); 2861 outAddr1.isValid(); 2862 outState1.setText(direction 2863 ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 2864 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 2865 break; 2866 } 2867 case 1: { 2868 // have read value for output3 - update local storage 2869 outAddr3.setText(readValueString); 2870 outAddr3.setLastQueriedValue(readValueString); 2871 outState3.setText(direction 2872 ? Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateClosed")) 2873 : Bundle.getMessage("LabelTurnoutCurrentStateX", Bundle.getMessage("BeanStateThrown"))); 2874 break; 2875 } 2876 case 16: 2877 case 20: 2878 case 24: 2879 case 28: 2880 case 32: 2881 case 36: 2882 case 40: 2883 case 44: { 2884 // have read value for Route n Top - update local storage 2885 Integer effectiveIndex = (indexToRead - 12) / 4; 2886 if (isUsed == false) { 2887 routeTop[effectiveIndex].setIsUnused(); 2888 routeTop[effectiveIndex].addressField.setText(""); 2889 routeTop[effectiveIndex].unusedRadioButton.setSelected(true); 2890 } else { 2891 routeTop[effectiveIndex].setAddress(readValue); 2892 routeTop[effectiveIndex].addressField.setText(readValueString); 2893 routeTop[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2894 if (opsw[46] == true) { 2895 routeTop[effectiveIndex].closedRadioButton.setSelected(true); 2896 } else { 2897 routeTop[effectiveIndex].thrownRadioButton.setSelected(true); 2898 } 2899 } 2900 break; 2901 } 2902 case 17: 2903 case 21: 2904 case 25: 2905 case 29: 2906 case 33: 2907 case 37: 2908 case 41: 2909 case 45: { 2910 // have a read value for Route n - update local storage 2911 Integer effectiveIndex = (indexToRead - 13) / 4; 2912 if (isUsed == false) { 2913 routeA3[effectiveIndex].setIsUnused(); 2914 routeA3[effectiveIndex].addressField.setText(""); 2915 routeA3[effectiveIndex].unusedRadioButton.setSelected(true); 2916 } else { 2917 routeA3[effectiveIndex].setAddress(readValue); 2918 routeA3[effectiveIndex].addressField.setText(readValueString); 2919 routeA3[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2920 if (opsw[46] == true) { 2921 routeA3[effectiveIndex].closedRadioButton.setSelected(true); 2922 } else { 2923 routeA3[effectiveIndex].thrownRadioButton.setSelected(true); 2924 } 2925 } 2926 break; 2927 } 2928 case 18: 2929 case 22: 2930 case 26: 2931 case 30: 2932 case 34: 2933 case 38: 2934 case 42: 2935 case 46: { 2936 // have a read value for Route n - update local storage 2937 Integer effectiveIndex = (indexToRead - 14) / 4; 2938 if (isUsed == false) { 2939 routeA5[effectiveIndex].setIsUnused(); 2940 routeA5[effectiveIndex].addressField.setText(""); 2941 routeA5[effectiveIndex].unusedRadioButton.setSelected(true); 2942 } else { 2943 routeA5[effectiveIndex].setAddress(readValue); 2944 routeA5[effectiveIndex].addressField.setText(readValueString); 2945 routeA5[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2946 if (opsw[46] == true) { 2947 routeA5[effectiveIndex].closedRadioButton.setSelected(true); 2948 } else { 2949 routeA5[effectiveIndex].thrownRadioButton.setSelected(true); 2950 } 2951 } 2952 break; 2953 } 2954 case 19: 2955 case 23: 2956 case 27: 2957 case 31: 2958 case 35: 2959 case 39: 2960 case 43: 2961 case 47: { 2962 // have a read value for Route n - update local storage 2963 Integer effectiveIndex = (indexToRead - 15) / 4; 2964 if (isUsed == false) { 2965 routeA7[effectiveIndex].setIsUnused(); 2966 routeA7[effectiveIndex].addressField.setText(""); 2967 routeA7[effectiveIndex].unusedRadioButton.setSelected(true); 2968 } else { 2969 routeA7[effectiveIndex].setAddress(readValue); 2970 routeA7[effectiveIndex].addressField.setText(readValueString); 2971 routeA7[effectiveIndex].addressField.setLastQueriedValue(readValueString); 2972 if (opsw[46] == true) { 2973 routeA7[effectiveIndex].closedRadioButton.setSelected(true); 2974 } else { 2975 routeA7[effectiveIndex].thrownRadioButton.setSelected(true); 2976 } 2977 } 2978 break; 2979 } 2980 default: { 2981 break; 2982 } 2983 } 2984 } 2985 2986 private final ActionListener basicConfigChangeActionListener = new ActionListener() { 2987 @Override 2988 public void actionPerformed(ActionEvent e) { 2989 if (e.getSource().getClass() == JComboBox.class) { 2990 switch (((Component) e.getSource()).getName()) { 2991 case "1": // NOI18N 2992 opsw[1] = (outputType.getSelectedIndex() == 1); 2993 updateGuiBasicOpSw(1); 2994 break; 2995 case "2345": // NOI18N 2996 int selection = delayTime.getSelectedIndex(); 2997 opsw[2] = ((selection & 0x1) == 1); 2998 opsw[3] = ((selection & 0x2) == 2); 2999 opsw[4] = ((selection & 0x4) == 4); 3000 opsw[5] = ((selection & 0x8) == 8); 3001 updateGuiBasicOpSw(2); 3002 updateGuiBasicOpSw(3); 3003 updateGuiBasicOpSw(4); 3004 updateGuiBasicOpSw(5); 3005 break; 3006 case "6": // NOI18N 3007 opsw[6] = (outputStates.getSelectedIndex() == 1); 3008 updateGuiBasicOpSw(6); 3009 break; 3010 case "8": // NOI18N 3011 opsw[8] = startupDelay.getSelectedIndex() == 1; 3012 updateGuiBasicOpSw(8); 3013 break; 3014 case "9": // NOI18N 3015 opsw[9] = staticOutputShutoff.getSelectedIndex() == 1; 3016 updateGuiBasicOpSw(9); 3017 break; 3018 case "10": // NOI18N 3019 opsw[10] = commandType.getSelectedIndex() == 1; 3020 updateGuiBasicOpSw(10); 3021 break; 3022 case "13": // NOI18N 3023 opsw[13] = (sensorMessageTrigger.getSelectedIndex() == 1); 3024 updateGuiBasicOpSw(13); 3025 break; 3026 case "14": // NOI18N 3027 opsw[14] = commandSource.getSelectedIndex() == 1; 3028 updateGuiBasicOpSw(14); 3029 break; 3030 case "21": // NOI18N 3031 opsw[21] = localSensorType.getSelectedIndex() == 1; 3032 updateGuiBasicOpSw(21); 3033 break; 3034 3035 case "1116": // NOI18N 3036 opsw[11] = (routesControl.getSelectedIndex() == 1) || (routesControl.getSelectedIndex() == 3); 3037 opsw[16] = routesControl.getSelectedIndex() >= 2; 3038 updateGuiBasicOpSw(11); 3039 updateGuiBasicOpSw(16); 3040 break; 3041 case "1215": // NOI18N 3042 opsw[12] = (localControlOfOutputsStyle.getSelectedIndex() & 1) == 1; //2 -> OpSw12="c" 3043 opsw[15] = (localControlOfOutputsStyle.getSelectedIndex() >= 2); //0 -> OpSw15="c" 3044 updateGuiBasicOpSw(12); 3045 updateGuiBasicOpSw(15); 3046 break; 3047 default: 3048 } 3049 } else if (e.getSource().getClass() == JCheckBox.class) { 3050 switch (((Component) e.getSource()).getName()) { 3051 case "17": // NOI18N 3052 opsw[17] = output1CrossbuckFlasherCheckBox.isSelected(); 3053 updateGuiBasicOpSw(17); 3054 break; 3055 case "18": // NOI18N 3056 opsw[18] = output2CrossbuckFlasherCheckBox.isSelected(); 3057 updateGuiBasicOpSw(18); 3058 break; 3059 case "19": // NOI18N 3060 opsw[19] = output3CrossbuckFlasherCheckBox.isSelected(); 3061 updateGuiBasicOpSw(19); 3062 break; 3063 case "20": // NOI18N 3064 opsw[20] = output4CrossbuckFlasherCheckBox.isSelected(); 3065 updateGuiBasicOpSw(20); 3066 break; 3067 default: 3068 break; 3069 } 3070 3071 } 3072 } 3073 }; 3074 3075 private void updateBasicOpSwTab() { 3076 for (int i = 1; i <= 21; ++i) { 3077 if (i != 7) { 3078 opswThrown[i].setSelected(!opsw[i]); 3079 opswClosed[i].setSelected(opsw[i]); 3080 } 3081 } 3082 } 3083 3084 private static class JRadioButtonWithInteger extends JRadioButton { 3085 3086 public int index; 3087 3088 JRadioButtonWithInteger(int i, String s) { 3089 super(s); 3090 index = i; 3091 } 3092 } 3093 3094 3095 /** 3096 * Copy from the GUI OpSw tab to the GUI Basics tab 3097 */ 3098 protected void copyOpswToBasic() { 3099 // copy over values from OpSw tab to the Basics tab 3100 outputType.setSelectedIndex(opsw[1]?1:0); 3101 3102 delayTime.setSelectedIndex( 3103 (opsw[2]?1:0) + (opsw[3]?2:0) + (opsw[4]?4:0) + (opsw[5]?8:0)); 3104 3105 outputStates.setSelectedIndex(opsw[6]?1:0); 3106 isWritingResetOpSw = opsw[7]; 3107 startupDelay.setSelectedIndex(opsw[8]?1:0); 3108 staticOutputShutoff.setSelectedIndex(opsw[9]?1:0); 3109 commandType.setSelectedIndex(opsw[10]?1:0); 3110 routesControl.setSelectedIndex((opsw[11]?1:0) + (opsw[16]?2:0)); 3111 localControlOfOutputsStyle.setSelectedIndex((opsw[12]?1:0) + (opsw[15]?2:0)); 3112 sensorMessageTrigger.setSelectedIndex(opsw[13]?1:0); 3113 commandSource.setSelectedIndex(opsw[14]?1:0); 3114 output1CrossbuckFlasherCheckBox.setSelected(opsw[17]); 3115 output2CrossbuckFlasherCheckBox.setSelected(opsw[18]); 3116 output3CrossbuckFlasherCheckBox.setSelected(opsw[19]); 3117 output4CrossbuckFlasherCheckBox.setSelected(opsw[20]); 3118 localSensorType.setSelectedIndex(opsw[21]?1:0); 3119 } 3120 3121 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Ds64TabbedPanel.class); 3122 3123}