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