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