001package jmri.jmrix.loconet.slotmon; 002 003import javax.swing.JButton; 004import javax.swing.JCheckBox; 005import javax.swing.JLabel; 006import javax.swing.JTable; 007import javax.swing.JTextField; 008 009import jmri.Throttle; 010import jmri.jmrix.loconet.LnConstants; 011import jmri.jmrix.loconet.LocoNetMessage; 012import jmri.jmrix.loconet.LocoNetSlot; 013import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 014import jmri.jmrix.loconet.SlotListener; 015import jmri.util.StringUtil; 016import jmri.util.swing.JmriJOptionPane; 017 018/** 019 * Table data model for display of slot manager contents. 020 * 021 * @author Bob Jacobsen Copyright (C) 2001 022 * @author Jeffrey Machacek 2013 023 */ 024public class SlotMonDataModel extends javax.swing.table.AbstractTableModel implements SlotListener { 025 026 static public final int SLOTCOLUMN = 0; 027 static public final int ESTOPCOLUMN = 1; 028 static public final int ADDRCOLUMN = 2; 029 static public final int SPDCOLUMN = 3; 030 static public final int TYPECOLUMN = 4; 031 static public final int STATCOLUMN = 5; // status: free, common, etc 032 static public final int DISPCOLUMN = 6; // originally "dispatch" button, now "free" 033 static public final int CONSCOLUMN = 7; // consist state 034 static public final int CONSISTADDRESS = 8; //consist address 035 static public final int THROTCOLUMN = 9; 036 static public final int DIRCOLUMN = 10; 037 static public final int F0COLUMN = 11; 038 static public final int F1COLUMN = 12; 039 static public final int F2COLUMN = 13; 040 static public final int F3COLUMN = 14; 041 static public final int F4COLUMN = 15; 042 static public final int F5COLUMN = 16; 043 static public final int F6COLUMN = 17; 044 static public final int F7COLUMN = 18; 045 static public final int F8COLUMN = 19; 046 static public final int F9COLUMN = 20; 047 static public final int F10COLUMN = 21; 048 static public final int F11COLUMN = 22; 049 static public final int F12COLUMN = 23; 050 static public final int F13COLUMN = 24; 051 static public final int F14COLUMN = 25; 052 static public final int F15COLUMN = 26; 053 static public final int F16COLUMN = 27; 054 static public final int F17COLUMN = 28; 055 static public final int F18COLUMN = 29; 056 static public final int F19COLUMN = 30; 057 static public final int F20COLUMN = 31; 058 static public final int F21COLUMN = 32; 059 static public final int F22COLUMN = 33; 060 static public final int F23COLUMN = 34; 061 static public final int F24COLUMN = 35; 062 static public final int F25COLUMN = 36; 063 static public final int F26COLUMN = 37; 064 static public final int F27COLUMN = 38; 065 static public final int F28COLUMN = 39; 066 067 //static public final int NUMCOLUMN = 40; Number of columns comes from the pane. 068 069 private int numRows = 128; 070 private int columns; 071 072 private final transient LocoNetSystemConnectionMemo memo; 073 074 SlotMonDataModel(int row, int column, LocoNetSystemConnectionMemo memo) { 075 this.memo = memo; 076 077 // number of columns 078 this.columns = column; 079 // set number of rows; 080 numRows = row; 081 082 // connect to SlotManager for updates 083 memo.getSlotManager().addSlotListener(SlotMonDataModel.this); 084 085 // start update process 086 memo.getSlotManager().update(); 087 } 088 089 /** 090 * Forces a refresh of the slots 091 */ 092 public void refreshSlots() { 093 memo.getSlotManager().update(); 094 } 095 096 /** 097 * Return the number of rows to be displayed. This can vary depending on 098 * whether only active rows are displayed, and whether the system slots 099 * should be displayed. 100 * <p> 101 * This should probably use a local cache instead of counting/searching each 102 * time. 103 * 104 * @return the number of rows 105 */ 106 @Override 107 public int getRowCount() { 108 return numRows; 109 } 110 111 @Override 112 public int getColumnCount() { 113 return columns; 114 } 115 116 @Override 117 public String getColumnName(int col) { 118 switch (col) { 119 case SLOTCOLUMN: 120 return Bundle.getMessage("SlotCol"); 121 case ESTOPCOLUMN: 122 return ""; // no heading, as button is clear 123 case ADDRCOLUMN: 124 return Bundle.getMessage("AddressCol"); 125 case SPDCOLUMN: 126 return Bundle.getMessage("SpeedCol"); 127 case TYPECOLUMN: 128 return Bundle.getMessage("StatusCol"); 129 case STATCOLUMN: 130 return Bundle.getMessage("UseCol"); 131 case CONSCOLUMN: 132 return Bundle.getMessage("ConsistedCol"); 133 case CONSISTADDRESS: 134 return Bundle.getMessage("ConsistAddress"); 135 case DIRCOLUMN: 136 return Bundle.getMessage("DirectionCol"); 137 case DISPCOLUMN: 138 return ""; // no heading, as button is clear 139 case F0COLUMN: 140 return Throttle.getFunctionString(0); 141 case F1COLUMN: 142 return Throttle.getFunctionString(1); 143 case F2COLUMN: 144 return Throttle.getFunctionString(2); 145 case F3COLUMN: 146 return Throttle.getFunctionString(3); 147 case F4COLUMN: 148 return Throttle.getFunctionString(4); 149 case F5COLUMN: 150 return Throttle.getFunctionString(5); 151 case F6COLUMN: 152 return Throttle.getFunctionString(6); 153 case F7COLUMN: 154 return Throttle.getFunctionString(7); 155 case F8COLUMN: 156 return Throttle.getFunctionString(8); 157 case F9COLUMN: 158 return Throttle.getFunctionString(9); 159 case F10COLUMN: 160 return Throttle.getFunctionString(10); 161 case F11COLUMN: 162 return Throttle.getFunctionString(11); 163 case F12COLUMN: 164 return Throttle.getFunctionString(12); 165 case F13COLUMN: 166 return Throttle.getFunctionString(13); 167 case F14COLUMN: 168 return Throttle.getFunctionString(14); 169 case F15COLUMN: 170 return Throttle.getFunctionString(15); 171 case F16COLUMN: 172 return Throttle.getFunctionString(16); 173 case F17COLUMN: 174 return Throttle.getFunctionString(17); 175 case F18COLUMN: 176 return Throttle.getFunctionString(16); 177 case F19COLUMN: 178 return Throttle.getFunctionString(19); 179 case F20COLUMN: 180 return Throttle.getFunctionString(20); 181 case F21COLUMN: 182 return Throttle.getFunctionString(21); 183 case F22COLUMN: 184 return Throttle.getFunctionString(22); 185 case F23COLUMN: 186 return Throttle.getFunctionString(23); 187 case F24COLUMN: 188 return Throttle.getFunctionString(24); 189 case F25COLUMN: 190 return Throttle.getFunctionString(25); 191 case F26COLUMN: 192 return Throttle.getFunctionString(26); 193 case F27COLUMN: 194 return Throttle.getFunctionString(27); 195 case F28COLUMN: 196 return Throttle.getFunctionString(28); 197 case THROTCOLUMN: 198 return Bundle.getMessage("ThrottleIDCol"); 199 default: 200 return "unknown"; // NOI18N 201 } 202 } 203 204 @Override 205 public Class<?> getColumnClass(int col) { 206 switch (col) { 207 case SLOTCOLUMN: 208 case ADDRCOLUMN: 209 case CONSISTADDRESS: 210 return Integer.class; 211 case SPDCOLUMN: 212 case TYPECOLUMN: 213 case STATCOLUMN: 214 case CONSCOLUMN: 215 case DIRCOLUMN: 216 case THROTCOLUMN: 217 return String.class; 218 case ESTOPCOLUMN: 219 case DISPCOLUMN: 220 return JButton.class; 221 case F0COLUMN: 222 case F1COLUMN: 223 case F2COLUMN: 224 case F3COLUMN: 225 case F4COLUMN: 226 case F5COLUMN: 227 case F6COLUMN: 228 case F7COLUMN: 229 case F8COLUMN: 230 case F9COLUMN: 231 case F10COLUMN: 232 case F11COLUMN: 233 case F12COLUMN: 234 case F13COLUMN: 235 case F14COLUMN: 236 case F15COLUMN: 237 case F16COLUMN: 238 case F17COLUMN: 239 case F18COLUMN: 240 case F19COLUMN: 241 case F20COLUMN: 242 case F21COLUMN: 243 case F22COLUMN: 244 case F23COLUMN: 245 case F24COLUMN: 246 case F25COLUMN: 247 case F26COLUMN: 248 case F27COLUMN: 249 case F28COLUMN: 250 return Boolean.class; 251 default: 252 return null; 253 } 254 } 255 256 @Override 257 public boolean isCellEditable(int row, int col) { 258 LocoNetSlot s = memo.getSlotManager().slot(row); 259 switch (col) { 260 case ESTOPCOLUMN: 261 case DISPCOLUMN: 262 case F0COLUMN: 263 case F1COLUMN: 264 case F2COLUMN: 265 case F3COLUMN: 266 case F4COLUMN: 267 case F5COLUMN: 268 case F6COLUMN: 269 case F7COLUMN: 270 case F8COLUMN: 271 case F9COLUMN: 272 case F10COLUMN: 273 case F11COLUMN: 274 case F12COLUMN: 275 case F13COLUMN: 276 case F14COLUMN: 277 case F15COLUMN: 278 case F16COLUMN: 279 case F17COLUMN: 280 case F18COLUMN: 281 case F19COLUMN: 282 case F20COLUMN: 283 case F21COLUMN: 284 case F22COLUMN: 285 case F23COLUMN: 286 case F24COLUMN: 287 case F25COLUMN: 288 case F26COLUMN: 289 case F27COLUMN: 290 case F28COLUMN: 291 // only loco slots to be marked writeable only, system slot are read only 292 return !s.isSystemSlot(); 293 default: 294 return false; 295 } 296 } 297 298 @Override 299 public Object getValueAt(int row, int col) { 300 LocoNetSlot s = memo.getSlotManager().slot(row); 301 String t; 302 if (s == null) { 303 log.error("slot pointer was null for slot row: {} col: {}", row, col); 304 return null; 305 } 306 307 switch (col) { 308 case SLOTCOLUMN: // slot number 309 return row; 310 case ESTOPCOLUMN: 311 return Bundle.getMessage("ButtonEstop"); // will be name of button in default GUI 312 case ADDRCOLUMN: 313 return s.locoAddr(); 314 case SPDCOLUMN: 315 switch (s.consistStatus()) { 316 case LnConstants.CONSIST_TOP: 317 case LnConstants.CONSIST_NO: 318 if (s.speed() == 1) { 319 t = "(estop) 1"; 320 } else { 321 t = " " + s.speed(); 322 } 323 return t.substring(t.length() - 9, t.length()); // 9 comes from length of the "(estop)" prefix 324 case LnConstants.CONSIST_MID: 325 case LnConstants.CONSIST_SUB: 326 return Bundle.getMessage("SlotSpeedConsist"); 327 default: 328 return Bundle.getMessage("StateError"); 329 } 330 case TYPECOLUMN: 331 switch (s.decoderType()) { 332 case LnConstants.DEC_MODE_128A: 333 return "128 step adv"; 334 case LnConstants.DEC_MODE_28A: 335 return " 28 step adv"; 336 case LnConstants.DEC_MODE_128: 337 return "128 step"; 338 case LnConstants.DEC_MODE_14: 339 return " 14 step"; 340 case LnConstants.DEC_MODE_28TRI: 341 return " 28 step trinary"; 342 case LnConstants.DEC_MODE_28: 343 return " 28 step"; 344 default: 345 return Bundle.getMessage("StateUnknown"); 346 } 347 case STATCOLUMN: 348 switch (s.slotStatus()) { 349 case LnConstants.LOCO_IN_USE: 350 return Bundle.getMessage("StateInUse"); 351 case LnConstants.LOCO_IDLE: 352 return Bundle.getMessage("StateIdle"); 353 case LnConstants.LOCO_COMMON: 354 return Bundle.getMessage("StateCommon"); 355 case LnConstants.LOCO_FREE: 356 return Bundle.getMessage("StateFree"); 357 default: 358 return Bundle.getMessage("StateError"); 359 } 360 case CONSCOLUMN: 361 switch (s.consistStatus()) { 362 case LnConstants.CONSIST_MID: 363 if (s.getProtocol() == LnConstants.LOCONETPROTOCOL_TWO) { 364 return Bundle.getMessage("SlotConsistMidX", s.getLeadSlot()); 365 } 366 t = Bundle.getMessage("SlotConsistMidX", s.speed()); 367 return t; 368 case LnConstants.CONSIST_TOP: 369 return Bundle.getMessage("SlotConsistTop"); 370 case LnConstants.CONSIST_SUB: 371 if (s.getProtocol() == LnConstants.LOCONETPROTOCOL_TWO) { 372 return Bundle.getMessage("SlotConsistSubX", s.getLeadSlot()); 373 } 374 t = Bundle.getMessage("SlotConsistSubX", s.speed()); 375 return t; 376 case LnConstants.CONSIST_NO: 377 return Bundle.getMessage("SlotConsistNone"); 378 default: 379 return Bundle.getMessage("StateError"); 380 } 381 case CONSISTADDRESS: 382 switch (s.consistStatus()) { 383 case LnConstants.CONSIST_TOP: 384 return s.locoAddr(); 385 case LnConstants.CONSIST_MID: 386 case LnConstants.CONSIST_SUB: 387 if (s.getProtocol() == LnConstants.LOCONETPROTOCOL_TWO) { 388 return memo.getSlotManager().slot(s.getLeadSlot()).locoAddr(); 389 } 390 return memo.getSlotManager().slot(s.speed()).locoAddr(); 391 case LnConstants.CONSIST_NO: 392 return 0; 393 default: 394 return 0; 395 } 396 case DISPCOLUMN: 397 return Bundle.getMessage("ButtonRelease"); // will be name of button in default GUI 398 case DIRCOLUMN: 399 return s.isForward() ? Bundle.getMessage("DirColForward") : Bundle.getMessage("DirColReverse"); 400 case F0COLUMN: 401 return s.isF0(); 402 case F1COLUMN: 403 return s.isF1(); 404 case F2COLUMN: 405 return s.isF2(); 406 case F3COLUMN: 407 return s.isF3(); 408 case F4COLUMN: 409 return s.isF4(); 410 case F5COLUMN: 411 return s.isF5(); 412 case F6COLUMN: 413 return s.isF6(); 414 case F7COLUMN: 415 return s.isF7(); 416 case F8COLUMN: 417 return s.isF8(); 418 case F9COLUMN: 419 return s.isF9(); 420 case F10COLUMN: 421 return s.isF10(); 422 case F11COLUMN: 423 return s.isF11(); 424 case F12COLUMN: 425 return s.isF12(); 426 case F13COLUMN: 427 return s.isF13(); 428 case F14COLUMN: 429 return s.isF14(); 430 case F15COLUMN: 431 return s.isF15(); 432 case F16COLUMN: 433 return s.isF16(); 434 case F17COLUMN: 435 return s.isF17(); 436 case F18COLUMN: 437 return s.isF18(); 438 case F19COLUMN: 439 return s.isF19(); 440 case F20COLUMN: 441 return s.isF20(); 442 case F21COLUMN: 443 return s.isF21(); 444 case F22COLUMN: 445 return s.isF22(); 446 case F23COLUMN: 447 return s.isF23(); 448 case F24COLUMN: 449 return s.isF24(); 450 case F25COLUMN: 451 return s.isF25(); 452 case F26COLUMN: 453 return s.isF26(); 454 case F27COLUMN: 455 return s.isF27(); 456 case F28COLUMN: 457 return s.isF28(); 458 case THROTCOLUMN: 459 int upper = (s.id() >> 7) & 0x7F; 460 int lower = s.id() & 0x7F; 461 return StringUtil.twoHexFromInt(upper) + " " + StringUtil.twoHexFromInt(lower); 462 463 default: 464 log.error("internal state inconsistent with table requst for {} {}", row, col); 465 return null; 466 } 467 } 468 469 public int getPreferredWidth(int col) { 470 switch (col) { 471 case SLOTCOLUMN: 472 return new JTextField(3).getPreferredSize().width; 473 case ESTOPCOLUMN: 474 return new JButton(Bundle.getMessage("ButtonEstop")).getPreferredSize().width; 475 case ADDRCOLUMN: 476 return new JTextField(5).getPreferredSize().width; 477 case SPDCOLUMN: 478 case STATCOLUMN: 479 return new JTextField(6).getPreferredSize().width; 480 case TYPECOLUMN: 481 return new JTextField(12).getPreferredSize().width; 482 case CONSCOLUMN: 483 return new JTextField(4).getPreferredSize().width; 484 case CONSISTADDRESS: 485 return new JTextField(" 0000 ").getPreferredSize().width; 486 case DIRCOLUMN: 487 // the length of an empty JTextField works on more GUIs 488 int m = Math.max(Bundle.getMessage("DirColForward").length(), Bundle.getMessage("DirColReverse").length()); 489 m = Math.max(m, Bundle.getMessage("DirectionCol").length()); 490 return new JTextField(m).getPreferredSize().width; 491 case DISPCOLUMN: 492 return new JButton(Bundle.getMessage("ButtonRelease")).getPreferredSize().width; 493 case THROTCOLUMN: 494 return new JTextField(7).getPreferredSize().width; 495 case F0COLUMN: 496 case F1COLUMN: 497 case F2COLUMN: 498 case F3COLUMN: 499 case F4COLUMN: 500 case F5COLUMN: 501 case F6COLUMN: 502 case F7COLUMN: 503 case F8COLUMN: 504 case F9COLUMN: 505 case F10COLUMN: 506 case F11COLUMN: 507 case F12COLUMN: 508 case F13COLUMN: 509 case F14COLUMN: 510 case F15COLUMN: 511 case F16COLUMN: 512 case F17COLUMN: 513 case F18COLUMN: 514 case F19COLUMN: 515 case F20COLUMN: 516 case F21COLUMN: 517 case F22COLUMN: 518 case F23COLUMN: 519 case F24COLUMN: 520 case F25COLUMN: 521 case F26COLUMN: 522 case F27COLUMN: 523 case F28COLUMN: 524 // to show checkboxes and Text 525 return Math.max(new JCheckBox().getPreferredSize().width, new JTextField("F99").getPreferredSize().width); 526 default: 527 return new JLabel(" <unknown> ").getPreferredSize().width; // NOI18N 528 } 529 } 530 531 @Override 532 public void setValueAt(Object value, int row, int col) { 533 LocoNetMessage msg; 534 LocoNetSlot s = memo.getSlotManager().slot(row); 535 if (s == null) { 536 log.error("slot pointer was null for slot row: {} col: {}", row, col); 537 return; 538 } 539 540 switch (col) { 541 case ESTOPCOLUMN: 542 log.debug("Start estop in slot {}", row); 543 if ((s.consistStatus() == LnConstants.CONSIST_SUB) 544 || (s.consistStatus() == LnConstants.CONSIST_MID)) { 545 Object[] options = {Bundle.getMessage("ButtonOK"), Bundle.getMessage("ButtonCancel")}; 546 int result = JmriJOptionPane.showOptionDialog(null, 547 Bundle.getMessage("SlotEstopWarning"), 548 Bundle.getMessage("WarningTitle"), 549 JmriJOptionPane.DEFAULT_OPTION, 550 JmriJOptionPane.WARNING_MESSAGE, 551 null, options, options[1]); 552 if ( result != 0 ) { // not array position 0 ButtonOK 553 return; 554 } 555 } 556 msg = s.writeSpeed(1); 557 memo.getLnTrafficController().sendLocoNetMessage(msg); 558 fireTableRowsUpdated(row, row); 559 break; 560 case F0COLUMN: 561 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 562 sendFunctionGroup1(s, col, row); 563 } else { 564 sendExpFunctionGroup1(s, col, row); 565 } 566 fireTableRowsUpdated(row, row); 567 break; 568 case F1COLUMN: 569 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 570 sendFunctionGroup1(s, col, row); 571 } else { 572 sendExpFunctionGroup1(s, col, row); 573 } 574 fireTableRowsUpdated(row, row); 575 break; 576 case F2COLUMN: 577 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 578 sendFunctionGroup1(s, col, row); 579 } else { 580 sendExpFunctionGroup1(s, col, row); 581 } 582 fireTableRowsUpdated(row, row); 583 break; 584 case F3COLUMN: 585 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 586 sendFunctionGroup1(s, col, row); 587 } else { 588 sendExpFunctionGroup1(s, col, row); 589 } 590 fireTableRowsUpdated(row, row); 591 break; 592 case F4COLUMN: 593 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 594 sendFunctionGroup1(s, col, row); 595 } else { 596 sendExpFunctionGroup1(s, col, row); 597 } 598 fireTableRowsUpdated(row, row); 599 break; 600 case F5COLUMN: 601 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 602 sendFunctionGroup2(s, col, row); 603 } else { 604 sendExpFunctionGroup1(s, col, row); 605 } 606 fireTableRowsUpdated(row, row); 607 break; 608 case F6COLUMN: 609 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 610 sendFunctionGroup2(s, col, row); 611 } else { 612 sendExpFunctionGroup1(s, col, row); 613 } 614 fireTableRowsUpdated(row, row); 615 break; 616 case F7COLUMN: 617 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 618 sendFunctionGroup2(s, col, row); 619 } else { 620 sendExpFunctionGroup2(s, col, row); 621 } 622 fireTableRowsUpdated(row, row); 623 break; 624 case F8COLUMN: 625 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 626 sendFunctionGroup2(s, col, row); 627 } else { 628 sendExpFunctionGroup2(s, col, row); 629 } 630 fireTableRowsUpdated(row, row); 631 break; 632 case F9COLUMN: 633 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 634 sendFunctionGroup3(s, col, row); 635 } else { 636 sendExpFunctionGroup2(s, col, row); 637 } 638 fireTableRowsUpdated(row, row); 639 break; 640 case F10COLUMN: 641 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 642 sendFunctionGroup3(s, col, row); 643 } else { 644 sendExpFunctionGroup2(s, col, row); 645 } 646 fireTableRowsUpdated(row, row); 647 break; 648 case F11COLUMN: 649 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 650 sendFunctionGroup3(s, col, row); 651 } else { 652 sendExpFunctionGroup2(s, col, row); 653 } 654 fireTableRowsUpdated(row, row); 655 break; 656 case F12COLUMN: 657 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 658 sendFunctionGroup3(s, col, row); 659 } else { 660 sendExpFunctionGroup2(s, col, row); 661 } 662 fireTableRowsUpdated(row, row); 663 break; 664 case F13COLUMN: 665 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 666 sendFunctionGroup4(s, col, row); 667 } else { 668 sendExpFunctionGroup2(s, col, row); 669 } 670 fireTableRowsUpdated(row, row); 671 break; 672 case F14COLUMN: 673 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 674 sendFunctionGroup4(s, col, row); 675 } else { 676 sendExpFunctionGroup3(s, col, row); 677 } 678 fireTableRowsUpdated(row, row); 679 break; 680 case F15COLUMN: 681 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 682 sendFunctionGroup4(s, col, row); 683 } else { 684 sendExpFunctionGroup3(s, col, row); 685 } 686 fireTableRowsUpdated(row, row); 687 break; 688 case F16COLUMN: 689 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 690 sendFunctionGroup4(s, col, row); 691 } else { 692 sendExpFunctionGroup3(s, col, row); 693 } 694 fireTableRowsUpdated(row, row); 695 break; 696 case F17COLUMN: 697 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 698 sendFunctionGroup4(s, col, row); 699 } else { 700 sendExpFunctionGroup3(s, col, row); 701 } 702 fireTableRowsUpdated(row, row); 703 break; 704 case F18COLUMN: 705 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 706 sendFunctionGroup4(s, col, row); 707 } else { 708 sendExpFunctionGroup3(s, col, row); 709 } 710 fireTableRowsUpdated(row, row); 711 break; 712 case F19COLUMN: 713 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 714 sendFunctionGroup4(s, col, row); 715 } else { 716 sendExpFunctionGroup3(s, col, row); 717 } 718 fireTableRowsUpdated(row, row); 719 break; 720 case F20COLUMN: 721 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 722 sendFunctionGroup4(s, col, row); 723 } else { 724 sendExpFunctionGroup3(s, col, row); 725 } 726 fireTableRowsUpdated(row, row); 727 break; 728 case F21COLUMN: 729 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 730 sendFunctionGroup5(s, col, row); 731 } else { 732 sendExpFunctionGroup4(s, col, row); 733 } 734 fireTableRowsUpdated(row, row); 735 break; 736 case F22COLUMN: 737 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 738 sendFunctionGroup5(s, col, row); 739 } else { 740 sendExpFunctionGroup4(s, col, row); 741 } 742 fireTableRowsUpdated(row, row); 743 break; 744 case F23COLUMN: 745 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 746 sendFunctionGroup5(s, col, row); 747 } else { 748 sendExpFunctionGroup4(s, col, row); 749 } 750 fireTableRowsUpdated(row, row); 751 break; 752 case F24COLUMN: 753 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 754 sendFunctionGroup5(s, col, row); 755 } else { 756 sendExpFunctionGroup4(s, col, row); 757 } 758 fireTableRowsUpdated(row, row); 759 break; 760 case F25COLUMN: 761 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 762 sendFunctionGroup5(s, col, row); 763 } else { 764 sendExpFunctionGroup4(s, col, row); 765 } 766 fireTableRowsUpdated(row, row); 767 break; 768 case F26COLUMN: 769 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 770 sendFunctionGroup5(s, col, row); 771 } else { 772 sendExpFunctionGroup4(s, col, row); 773 } 774 fireTableRowsUpdated(row, row); 775 break; 776 case F27COLUMN: 777 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 778 sendFunctionGroup5(s, col, row); 779 } else { 780 sendExpFunctionGroup4(s, col, row); 781 } 782 fireTableRowsUpdated(row, row); 783 break; 784 case F28COLUMN: 785 if (s.getProtocol() != LnConstants.LOCONETPROTOCOL_TWO) { 786 sendFunctionGroup5(s, col, row); 787 } else { 788 sendExpFunctionGroup4(s, col, row); 789 } 790 fireTableRowsUpdated(row, row); 791 break; 792 case DISPCOLUMN: 793 log.debug("Start freeing slot {}", row); 794 if (s.slotStatus() != LnConstants.LOCO_FREE) { 795 if (s.consistStatus() != LnConstants.CONSIST_NO) { 796 // Freeing a member takes it out of the consist 797 // entirely (i.e., while the slot is LOCO_FREE, it 798 // still reads the former consist information, but 799 // the next time that loco is selected, it comes 800 // back as CONSIST_NO). Freeing the CONSIST_TOP 801 // will kill the entire consist. 802 Object[] options = {Bundle.getMessage("ButtonOK"), Bundle.getMessage("ButtonCancel")}; 803 int result = JmriJOptionPane.showOptionDialog(null, 804 "Freeing a consist member will destroy the consist.\n\nAre you sure you want to do that?", 805 Bundle.getMessage("WarningTitle"), 806 JmriJOptionPane.DEFAULT_OPTION, 807 JmriJOptionPane.WARNING_MESSAGE, 808 null, options, options[1]); 809 if ( result != 0 ) { // not array position 0, ButtonOK 810 return; 811 } 812 } 813 // send status to free 814 memo.getLnTrafficController().sendLocoNetMessage( 815 s.writeStatus(LnConstants.LOCO_FREE)); 816 } else { 817 log.debug("Slot not in use"); 818 } 819 fireTableRowsUpdated(row, row); 820 break; 821 default: 822 // nothing to do if column not recognized 823 break; 824 } 825 } 826 827 //Added by Jeffrey Machacek, date: 2013 828 //changed 8/22/2013 829 public void clearAllSlots() { 830 int count = getRowCount(); 831 832 for (int row = 0; row < (count - 1); row++) { 833 LocoNetSlot s = memo.getSlotManager().slot(row); 834 835 if ((s.slotStatus() != LnConstants.LOCO_IN_USE) && (s.consistStatus() == LnConstants.CONSIST_NO)) { 836 log.debug("Freeing {} from slot {}, old status: {}", s.locoAddr(), s.getSlot(), s.slotStatus()); 837 memo.getLnTrafficController().sendLocoNetMessage( 838 s.writeStatus(LnConstants.LOCO_FREE 839 )); 840 fireTableRowsUpdated(row, row); 841 } 842 count = getRowCount(); 843 } 844 } 845 846 /** 847 * Configure a table to have our standard rows and columns. This is 848 * optional, in that other table formats can use this table model. But we 849 * put it here to help keep it consistent. 850 * 851 * @param slotTable the table to configure 852 */ 853 public void configureTable(JTable slotTable) { 854 } 855 856 // methods to communicate with SlotManager 857 @Override 858 public synchronized void notifyChangedSlot(LocoNetSlot s) { 859 // update model from this slot 860 int slotNum = s.getSlot(); 861 int slotStatus2; 862 863 if (slotNum == LnConstants.CFG_SLOT) { 864 slotStatus2 = s.ss2() & 0x78; // Bit 3-6 of SS2 contains SW36-39 of the CFG_SLOT 865 if (slotStatus2 > 0) { 866 memo.getSlotManager().update(); 867 } 868 } else { 869 slotNum = -1; // all rows 870 } 871 872 // notify the JTable object that a row has changed; do that in the Swing thread! 873 javax.swing.SwingUtilities.invokeLater(new Notify(slotNum, this)); 874 } 875 876 static private class Notify implements Runnable { 877 878 private final int _row; 879 javax.swing.table.AbstractTableModel _model; 880 881 public Notify(int row, javax.swing.table.AbstractTableModel model) { 882 _row = row; 883 _model = model; 884 } 885 886 @Override 887 public void run() { 888 if (-1 == _row) { // notify about entire table 889 _model.fireTableDataChanged(); // just that row 890 } else { 891 // notify that _row has changed 892 _model.fireTableRowsUpdated(_row, _row); // just that row 893 } 894 } 895 } 896 897 protected LocoNetSlot getSlot(int row) { 898 return memo.getSlotManager().slot(row); 899 } 900 901 /** 902 * This is a convenience method that makes it easier for classes using this 903 * model to set all in-use slots to emergency stop 904 */ 905 public void estopAll() { 906 for (int slotNum = 0; slotNum < 120; slotNum++) { 907 LocoNetSlot s = memo.getSlotManager().slot(slotNum); 908 if (s.slotStatus() != LnConstants.LOCO_FREE 909 && (s.consistStatus() == LnConstants.CONSIST_NO 910 || s.consistStatus() == LnConstants.CONSIST_TOP) 911 && s.speed() != 1) { 912 // send message to estop this loco 913 LocoNetMessage msg = s.writeSpeed(1) ; // emergency stop 914 memo.getLnTrafficController().sendLocoNetMessage(msg); 915 } 916 } 917 } 918 919 /** 920 * Send the LocoNet message to set the state of locomotive direction and 921 * functions F0, F1, F2, F3, F4 922 * @param slot loconet slot 923 * @param col grid col 924 * @param row grid row 925 */ 926 protected void sendFunctionGroup1(LocoNetSlot slot, int col, int row) { 927 log.debug("F0-F4 change requested {}", row); 928 if (slot == null) { 929 log.error("slot pointer was null for slot row: {} col: {}", row, col); 930 return; 931 } 932 boolean tempF0 = (col == F0COLUMN) ? !slot.isF0() : slot.isF0(); 933 boolean tempF1 = (col == F1COLUMN) ? !slot.isF1() : slot.isF1(); 934 boolean tempF2 = (col == F2COLUMN) ? !slot.isF2() : slot.isF2(); 935 boolean tempF3 = (col == F3COLUMN) ? !slot.isF3() : slot.isF3(); 936 boolean tempF4 = (col == F4COLUMN) ? !slot.isF4() : slot.isF4(); 937 938 int new_dirf = ((slot.isForward() ? 0 : LnConstants.DIRF_DIR) 939 | (tempF0 ? LnConstants.DIRF_F0 : 0) 940 | (tempF1 ? LnConstants.DIRF_F1 : 0) 941 | (tempF2 ? LnConstants.DIRF_F2 : 0) 942 | (tempF3 ? LnConstants.DIRF_F3 : 0) 943 | (tempF4 ? LnConstants.DIRF_F4 : 0)); 944 945 // set status to 'In Use' if other 946 int status = slot.slotStatus(); 947 if (status != LnConstants.LOCO_IN_USE) { 948 memo.getLnTrafficController().sendLocoNetMessage( 949 slot.writeStatus(LnConstants.LOCO_IN_USE 950 )); 951 } 952 LocoNetMessage msg = new LocoNetMessage(4); 953 msg.setOpCode(LnConstants.OPC_LOCO_DIRF); 954 msg.setElement(1, slot.getSlot()); 955 msg.setElement(2, new_dirf); // 1 here is estop 956 memo.getLnTrafficController().sendLocoNetMessage(msg); 957 // Delay here allows command station time to xmit on the rails. 958 try { 959 Thread.sleep(100); 960 } catch (InterruptedException ex) { 961 log.error("Interuppted Sleep", ex); 962 } 963 // reset status to original value if not previously 'in use' 964 if (status != LnConstants.LOCO_IN_USE) { 965 memo.getLnTrafficController().sendLocoNetMessage( 966 slot.writeStatus(status)); 967 } 968 } 969 970 /** 971 * Send the LocoNet message to set the state of functions F5, F6, F7, F8 972 * @param slot loconet slot 973 * @param col grid col 974 * @param row grid row 975 */ 976 protected void sendFunctionGroup2(LocoNetSlot slot, int col, int row) { 977 boolean tempF5 = (col == F5COLUMN) ? !slot.isF5() : slot.isF5(); 978 boolean tempF6 = (col == F6COLUMN) ? !slot.isF6() : slot.isF6(); 979 boolean tempF7 = (col == F7COLUMN) ? !slot.isF7() : slot.isF7(); 980 boolean tempF8 = (col == F8COLUMN) ? !slot.isF8() : slot.isF8(); 981 982 int new_snd = ((tempF8 ? LnConstants.SND_F8 : 0) 983 | (tempF7 ? LnConstants.SND_F7 : 0) 984 | (tempF6 ? LnConstants.SND_F6 : 0) 985 | (tempF5 ? LnConstants.SND_F5 : 0)); 986 987 // set status to 'In Use' if other 988 int status = slot.slotStatus(); 989 if (status != LnConstants.LOCO_IN_USE) { 990 memo.getLnTrafficController().sendLocoNetMessage( 991 slot.writeStatus(LnConstants.LOCO_IN_USE 992 )); 993 } 994 995 LocoNetMessage msg = new LocoNetMessage(4); 996 msg.setOpCode(LnConstants.OPC_LOCO_SND); 997 msg.setElement(1, slot.getSlot()); 998 msg.setElement(2, new_snd); // 1 here is estop 999 memo.getLnTrafficController().sendLocoNetMessage(msg); 1000 // Delay here allows command station time to xmit on the rails. 1001 try { 1002 Thread.sleep(100); 1003 } catch (InterruptedException ex) { 1004 log.error("Interuppted Sleep", ex); 1005 } 1006 1007 // reset status to original value if not previously 'in use' 1008 if (status != LnConstants.LOCO_IN_USE) { 1009 memo.getLnTrafficController().sendLocoNetMessage( 1010 slot.writeStatus(status)); 1011 } 1012 } 1013 1014 /** 1015 * Sends Function Group 3 values - F9 thru F12, using an "OPC_IMM_PACKET" LocoNet 1016 * Message. 1017 * @param slot loconet slot 1018 * @param col grid col 1019 * @param row grid row 1020 */ 1021 protected void sendFunctionGroup3(LocoNetSlot slot, int col, int row) { 1022 // LocoNet practice is to send F9-F12 as a DCC packet 1023 boolean tempF9 = (col == F9COLUMN) ? !slot.isF9() : slot.isF9(); 1024 boolean tempF10 = (col == F10COLUMN) ? !slot.isF10() : slot.isF10(); 1025 boolean tempF11 = (col == F11COLUMN) ? !slot.isF11() : slot.isF11(); 1026 boolean tempF12 = (col == F12COLUMN) ? !slot.isF12() : slot.isF12(); 1027 byte[] result = jmri.NmraPacket.function9Through12Packet(slot.locoAddr(), (slot.locoAddr() >= 128), 1028 tempF9, tempF10, tempF11, tempF12); 1029 1030 log.debug("sendFunctionGroup3 sending {} to LocoNet slot {}", result, slot.getSlot()); 1031 memo.get(jmri.CommandStation.class).sendPacket(result, 4); // repeat = 4 1032 } 1033 1034 /** 1035 * Sends Function Group 4 values - F13 thru F20, using an "OPC_IMM_PACKET" LocoNet 1036 * Message. 1037 * @param slot loconet slot 1038 * @param col grid col 1039 * @param row grid row 1040 */ 1041 protected void sendFunctionGroup4(LocoNetSlot slot, int col, int row) { 1042 // LocoNet practice is to send F13-F20 as a DCC packet 1043 boolean tempF13 = (col == F13COLUMN) ? !slot.isF13() : slot.isF13(); 1044 boolean tempF14 = (col == F14COLUMN) ? !slot.isF14() : slot.isF14(); 1045 boolean tempF15 = (col == F15COLUMN) ? !slot.isF15() : slot.isF15(); 1046 boolean tempF16 = (col == F16COLUMN) ? !slot.isF16() : slot.isF16(); 1047 boolean tempF17 = (col == F17COLUMN) ? !slot.isF17() : slot.isF17(); 1048 boolean tempF18 = (col == F18COLUMN) ? !slot.isF18() : slot.isF18(); 1049 boolean tempF19 = (col == F19COLUMN) ? !slot.isF19() : slot.isF19(); 1050 boolean tempF20 = (col == F20COLUMN) ? !slot.isF20() : slot.isF20(); 1051 byte[] result = jmri.NmraPacket.function13Through20Packet(slot.locoAddr(), (slot.locoAddr() >= 128), 1052 tempF13, tempF14, tempF15, tempF16, 1053 tempF17, tempF18, tempF19, tempF20); 1054 1055 log.debug("sendFunctionGroup4 sending {} to LocoNet slot {}", result, slot.getSlot()); 1056 memo.get(jmri.CommandStation.class).sendPacket(result, 4); // repeat = 4 1057 } 1058 1059 /** 1060 * Sends Function Group 5 values - F21 thru F28, using an "OPC_IMM_PACKET" LocoNet 1061 * Message. 1062 * @param slot loconet slot 1063 * @param col grid col 1064 * @param row grid row 1065 */ 1066 protected void sendFunctionGroup5(LocoNetSlot slot, int col, int row) { 1067 // LocoNet practice is to send F21-F28 as a DCC packet 1068 // LocoNet practice is to send F13-F20 as a DCC packet 1069 boolean tempF21 = (col == F21COLUMN) ? !slot.isF21() : slot.isF21(); 1070 boolean tempF22 = (col == F22COLUMN) ? !slot.isF22() : slot.isF22(); 1071 boolean tempF23 = (col == F23COLUMN) ? !slot.isF23() : slot.isF23(); 1072 boolean tempF24 = (col == F24COLUMN) ? !slot.isF24() : slot.isF24(); 1073 boolean tempF25 = (col == F25COLUMN) ? !slot.isF25() : slot.isF25(); 1074 boolean tempF26 = (col == F26COLUMN) ? !slot.isF26() : slot.isF26(); 1075 boolean tempF27 = (col == F27COLUMN) ? !slot.isF27() : slot.isF27(); 1076 boolean tempF28 = (col == F28COLUMN) ? !slot.isF28() : slot.isF28(); 1077 byte[] result = jmri.NmraPacket.function21Through28Packet(slot.locoAddr(), (slot.locoAddr() >= 128), 1078 tempF21, tempF22, tempF23, tempF24, 1079 tempF25, tempF26, tempF27, tempF28); 1080 1081 log.debug("sendFunctionGroup5 sending {} to LocoNet slot {}", result, slot.getSlot()); 1082 memo.get(jmri.CommandStation.class).sendPacket(result, 4); // repeat = 4 1083 } 1084 1085 /** 1086 * Send the Expanded LocoNet message to set the state of locomotive direction and 1087 * functions F0, F1, F2, F3, F4, F5, F6 1088 * @param slot loconet slot 1089 * @param col grid col 1090 * @param row grid row 1091 */ 1092 protected void sendExpFunctionGroup1(LocoNetSlot slot, int col, int row) { 1093 boolean tempF0 = (col == F0COLUMN) ? !slot.isF0() : slot.isF0(); 1094 boolean tempF1 = (col == F1COLUMN) ? !slot.isF1() : slot.isF1(); 1095 boolean tempF2 = (col == F2COLUMN) ? !slot.isF2() : slot.isF2(); 1096 boolean tempF3 = (col == F3COLUMN) ? !slot.isF3() : slot.isF3(); 1097 boolean tempF4 = (col == F4COLUMN) ? !slot.isF4() : slot.isF4(); 1098 boolean tempF5 = (col == F5COLUMN) ? !slot.isF5() : slot.isF5(); 1099 boolean tempF6 = (col == F6COLUMN) ? !slot.isF6() : slot.isF6(); 1100 int new_F0F6 = ((tempF5 ? 0b00100000 : 0) | (tempF6 ? 0b01000000 : 0) 1101 | (tempF0 ? LnConstants.DIRF_F0 : 0) 1102 | (tempF1 ? LnConstants.DIRF_F1 : 0) 1103 | (tempF2 ? LnConstants.DIRF_F2 : 0) 1104 | (tempF3 ? LnConstants.DIRF_F3 : 0) 1105 | (tempF4 ? LnConstants.DIRF_F4 : 0)); 1106 LocoNetMessage msg = new LocoNetMessage(6); 1107 msg.setOpCode(0xd5); 1108 msg.setElement(1, (slot.getSlot() / 128) | 0b00010000 ); 1109 msg.setElement(2,slot.getSlot() & 0b01111111); 1110 msg.setElement(3,slot.id() & 0x7F); 1111 msg.setElement(4, new_F0F6); 1112 memo.getLnTrafficController().sendLocoNetMessage(msg); 1113 } 1114 1115 /** 1116 * Send the Expanded LocoNet message to set the state of functions F7, F8, F8, F9, F10, F11, F12, F13 1117 * @param slot loconet slot 1118 * @param col grid col 1119 * @param row grid row 1120 */ 1121 protected void sendExpFunctionGroup2(LocoNetSlot slot, int col, int row) { 1122 boolean tempF7 = (col == F7COLUMN) ? !slot.isF7() : slot.isF7(); 1123 boolean tempF8 = (col == F8COLUMN) ? !slot.isF8() : slot.isF8(); 1124 boolean tempF9 = (col == F9COLUMN) ? !slot.isF9() : slot.isF9(); 1125 boolean tempF10 = (col == F10COLUMN) ? !slot.isF10() : slot.isF10(); 1126 boolean tempF11 = (col == F11COLUMN) ? !slot.isF11() : slot.isF11(); 1127 boolean tempF12 = (col == F12COLUMN) ? !slot.isF12() : slot.isF12(); 1128 boolean tempF13 = (col == F13COLUMN) ? !slot.isF13() : slot.isF13(); 1129 int new_F7F13 = ((tempF7 ? 0b00000001 : 0) | (tempF8 ? 0b00000010 : 0) 1130 | (tempF9 ? 0b00000100 : 0) 1131 | (tempF10 ? 0b00001000 : 0) 1132 | (tempF11 ? 0b00010000 : 0) 1133 | (tempF12 ? 0b00100000 : 0) 1134 | (tempF13 ? 0b01000000 : 0)); 1135 LocoNetMessage msg = new LocoNetMessage(6); 1136 msg.setOpCode(0xd5); 1137 msg.setElement(1, (slot.getSlot() / 128) | 0b00011000 ); 1138 msg.setElement(2,slot.getSlot() & 0b01111111); 1139 msg.setElement(3,slot.id() & 0x7F); 1140 msg.setElement(4, new_F7F13); 1141 memo.getLnTrafficController().sendLocoNetMessage(msg); 1142 } 1143 1144 /** 1145 * Sends expanded loconet message F14 thru F20 1146 * Message. 1147 * @param slot loconet slot 1148 * @param col grid col 1149 * @param row grid row 1150 */ 1151 protected void sendExpFunctionGroup3(LocoNetSlot slot, int col, int row) { 1152 boolean tempF14 = (col == F14COLUMN) ? !slot.isF14() : slot.isF14(); 1153 boolean tempF15 = (col == F15COLUMN) ? !slot.isF15() : slot.isF15(); 1154 boolean tempF16 = (col == F16COLUMN) ? !slot.isF16() : slot.isF16(); 1155 boolean tempF17 = (col == F17COLUMN) ? !slot.isF17() : slot.isF17(); 1156 boolean tempF18 = (col == F18COLUMN) ? !slot.isF18() : slot.isF18(); 1157 boolean tempF19 = (col == F19COLUMN) ? !slot.isF19() : slot.isF19(); 1158 boolean tempF20 = (col == F20COLUMN) ? !slot.isF20() : slot.isF20(); 1159 int new_F14F20 = ((tempF14 ? 0b00000001 : 0) | (tempF15 ? 0b00000010 : 0) 1160 | (tempF16 ? 0b00000100 : 0) 1161 | (tempF17 ? 0b00001000 : 0) 1162 | (tempF18 ? 0b00010000 : 0) 1163 | (tempF19 ? 0b00100000 : 0) 1164 | (tempF20 ? 0b01000000 : 0)); 1165 LocoNetMessage msg = new LocoNetMessage(6); 1166 msg.setOpCode(0xd5); 1167 msg.setElement(1, (slot.getSlot() / 128) | 0b00100000 ); 1168 msg.setElement(2,slot.getSlot() & 0b01111111); 1169 msg.setElement(3,slot.id() & 0x7F); 1170 msg.setElement(4, new_F14F20); 1171 memo.getLnTrafficController().sendLocoNetMessage(msg); 1172 } 1173 1174 /** 1175 * Sends Expanded loconet message F21 thru F28 Message. 1176 * @param slot loconet slot 1177 * @param col grid col 1178 * @param row grid row 1179 */ 1180 protected void sendExpFunctionGroup4(LocoNetSlot slot, int col, int row) { 1181 boolean tempF21 = (col == F21COLUMN) ? !slot.isF21() : slot.isF21(); 1182 boolean tempF22 = (col == F22COLUMN) ? !slot.isF22() : slot.isF22(); 1183 boolean tempF23 = (col == F23COLUMN) ? !slot.isF23() : slot.isF23(); 1184 boolean tempF24 = (col == F24COLUMN) ? !slot.isF24() : slot.isF24(); 1185 boolean tempF25 = (col == F25COLUMN) ? !slot.isF25() : slot.isF25(); 1186 boolean tempF26 = (col == F26COLUMN) ? !slot.isF26() : slot.isF26(); 1187 boolean tempF27 = (col == F27COLUMN) ? !slot.isF27() : slot.isF27(); 1188 boolean tempF28 = (col == F28COLUMN) ? !slot.isF28() : slot.isF28(); 1189 int new_F14F20 = ((tempF21 ? 0b00000001 : 0) | 1190 (tempF22 ? 0b00000010 : 0) | 1191 (tempF23 ? 0b00000100 : 0) | 1192 (tempF24 ? 0b00001000 : 0) | 1193 (tempF25 ? 0b00010000 : 0) | 1194 (tempF26 ? 0b00100000 : 0) | 1195 (tempF27 ? 0b01000000 : 0)); 1196 LocoNetMessage msg = new LocoNetMessage(6); 1197 msg.setOpCode(0xd5); 1198 if (!tempF28) { 1199 msg.setElement(1, (slot.getSlot() / 128) | LnConstants.OPC_EXP_SEND_FUNCTION_GROUP_F21F28_F28OFF); 1200 } else { 1201 msg.setElement(1, (slot.getSlot() / 128) | LnConstants.OPC_EXP_SEND_FUNCTION_GROUP_F21F28_F28ON); 1202 } 1203 msg.setElement(2, slot.getSlot() & 0x7F); 1204 msg.setElement(3, slot.id() & 0x7F); 1205 msg.setElement(4, new_F14F20); 1206 memo.getLnTrafficController().sendLocoNetMessage(msg); 1207 } 1208 1209 // gets called on SlotMonPane.dispose 1210 public void dispose() { 1211 memo.getSlotManager().removeSlotListener(this); 1212 } 1213 1214 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SlotMonDataModel.class); 1215 1216}