001package jmri.jmrix.can.cbus.swing.modules.merg; 002 003 004import java.awt.*; 005 006import javax.swing.*; 007import javax.swing.event.TableModelEvent; 008 009import jmri.jmrix.can.cbus.node.CbusNode; 010import jmri.jmrix.can.cbus.node.CbusNodeNVTableDataModel; 011import jmri.jmrix.can.cbus.swing.modules.*; 012 013//import org.slf4j.Logger; 014//import org.slf4j.LoggerFactory; 015 016/** 017 * Node Variable edit frame for a MERG CANACC8 CBUS module 018 * 019 * @author Andrew Crosland Copyright (C) 2021 020 */ 021public class CanCmdEditNVPane extends AbstractEditNVPane { 022 023 private static final int USER_FLAGS = 0; 024 private static final int OPS_FLAGS = 1; 025 private static final int DEBUG_FLAGS = 2; 026 private CmdStaFlags [] csFlags = new CmdStaFlags[3]; 027 028 private final UpdateNV cmdStaNoUpdateFn = new UpdateCmdStaNo(); 029 private final UpdateNV currentLimitUpdateFn = new UpdateCurrentLimit(); 030 private final UpdateNV nnMapUpdateFn = new UpdateNnMap(); 031 private final UpdateNV flagUpdateFn = new UpdateFlags(); 032 private final UpdateNV sodDelayUpdateFn = new UpdateSodDelay(); 033 private final UpdateNV intervalUpdateFn = new UpdateInterval(); 034 private final UpdateNV ackUpdateFn = new UpdateAck(); 035 private final UpdateNV multUpdateFn = new UpdateMult(); 036 private final UpdateNV walkaboutUpdateFn = new UpdateWalkabout(); 037 038 private TitledSpinner cmdStaNoSpinner; 039 private TitledSpinner mainSpinner; 040 private TitledSpinner progSpinner; 041 private TitledSpinner nnMapDccSpinner; 042 private TitledSpinner sodDelaySpinner; 043 private TitledSpinner intervalSpinner; 044 private TitledSpinner ackSpinner; 045 private TitledSpinner multSpinner; 046 private TitledSpinner walkaboutSpinner; 047 048 protected String flagTitleStrings[] = new String[] { 049 Bundle.getMessage("UserFlags"), 050 Bundle.getMessage("OperationsFlags"), 051 Bundle.getMessage("DebugFlags") 052 }; 053 054 protected String flagStrings[][] = new String[][] { 055 // User 056 {Bundle.getMessage("Silent"), 057 Bundle.getMessage("PermitSteal"), 058 Bundle.getMessage("PermitShare"), 059 Bundle.getMessage("PermitEvReset"), 060 Bundle.getMessage("MapEvents"), 061 Bundle.getMessage("StopOnTimeout"), 062 Bundle.getMessage("StartOfDay"), 063 Bundle.getMessage("Reserved")}, 064 // Ops 065 {Bundle.getMessage("JumperControl"), 066 Bundle.getMessage("MainOnBoard"), 067 Bundle.getMessage("AnalogDetect"), 068 Bundle.getMessage("ZtcMode"), 069 Bundle.getMessage("AllStopTrackOff"), 070 Bundle.getMessage("Reserved"), 071 Bundle.getMessage("Reserved"), 072 Bundle.getMessage("Reserved")}, 073 // Debug 074 {Bundle.getMessage("PriPkts"), 075 Bundle.getMessage("SpdPkts"), 076 Bundle.getMessage("FnPkts"), 077 Bundle.getMessage("ServicePkts"), 078 Bundle.getMessage("AccyPkts"), 079 Bundle.getMessage("Reserved"), 080 Bundle.getMessage("Reserved"), 081 Bundle.getMessage("Reserved") 082 }}; 083 084 protected String flagTtStrings[][] = new String[][] { 085 // User 086 {Bundle.getMessage("SilentTt"), 087 Bundle.getMessage("PermitStealTt"), 088 Bundle.getMessage("PermitShareTt"), 089 Bundle.getMessage("PermitEvResetTt"), 090 Bundle.getMessage("MapEventsTt"), 091 Bundle.getMessage("StopOnTimeoutTt"), 092 Bundle.getMessage("StartOfDayTt"), 093 Bundle.getMessage("ReservedTt")}, 094 // Ops 095 {Bundle.getMessage("JumperControlTt"), 096 Bundle.getMessage("MainOnBoardTt"), 097 Bundle.getMessage("AnalogDetectTt"), 098 Bundle.getMessage("ZtcModeTt"), 099 Bundle.getMessage("AllStopTrackOffTt"), 100 Bundle.getMessage("ReservedTt"), 101 Bundle.getMessage("ReservedTt"), 102 Bundle.getMessage("ReservedTt")}, 103 // Debug 104 {Bundle.getMessage("PriPktsTt"), 105 Bundle.getMessage("SpdPktsTt"), 106 Bundle.getMessage("FnPktsTt"), 107 Bundle.getMessage("ServicePktsTt"), 108 Bundle.getMessage("AccyPktsTt"), 109 Bundle.getMessage("ReservedTt"), 110 Bundle.getMessage("ReservedTt"), 111 Bundle.getMessage("ReservedTt") 112 }}; 113 114 protected CanCmdEditNVPane(CbusNodeNVTableDataModel dataModel, CbusNode node) { 115 super(dataModel, node); 116 } 117 118 /** {@inheritDoc} */ 119 @Override 120 public AbstractEditNVPane getContent() { 121 122 JTabbedPane tabbedPane = new JTabbedPane(); 123 124 JPanel cmdStaPane = new CmdStaPane(); 125 JPanel dccPane = new DccPane(); 126 JPanel cbusPane = new CbusPane(); 127 tabbedPane.addTab(Bundle.getMessage("CmdSta"), cmdStaPane); 128 tabbedPane.addTab("DCC", dccPane); 129 tabbedPane.addTab("CBUS", cbusPane); 130 131 JScrollPane scroll = new JScrollPane(tabbedPane); 132 add(scroll); 133 134 return this; 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 public void tableChanged(TableModelEvent e) { 140 if (e.getType() == TableModelEvent.UPDATE) { 141 int row = e.getFirstRow(); 142 int nv = row + 1; 143 int value = getSelectValue8(nv); 144 145 switch (nv) { 146 case CanCmdPaneProvider.CMD_STATION_NUMBER: 147 cmdStaNoSpinner.setValue(value); 148 break; 149 150 case CanCmdPaneProvider.USER_FLAGS: 151 csFlags[0].setFlags(value); 152 break; 153 154 case CanCmdPaneProvider.OPERATIONS_FLAGS: 155 csFlags[1].setFlags(value); 156 break; 157 158 case CanCmdPaneProvider.DEBUG_FLAGS: 159 csFlags[2].setFlags(value); 160 break; 161 162 case CanCmdPaneProvider.PROG_TRACK_CURRENT_LIMIT: 163 progSpinner.setValue(value); 164 break; 165 166 case CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT: 167 mainSpinner.setValue(value); 168 break; 169 170 case CanCmdPaneProvider.NN_MAP_DCC_HI: 171 case CanCmdPaneProvider.NN_MAP_DCC_LO: 172 nnMapDccSpinner.setValue(getSelectValue16(CanCmdPaneProvider.NN_MAP_DCC_HI, 173 CanCmdPaneProvider.NN_MAP_DCC_LO, 174 CanCmdPaneProvider.MIN_NN, 175 CanCmdPaneProvider.MAX_NN)); 176 break; 177 178 case CanCmdPaneProvider.WALKABOUT_TIMEOUT: 179 walkaboutSpinner.setValue(value); 180 break; 181 182 case CanCmdPaneProvider.CURRENT_MULTIPLIER: 183 multSpinner.setValue(value); 184 break; 185 186 case CanCmdPaneProvider.INC_CURRENT_FOR_ACK: 187 ackSpinner.setValue(value); 188 break; 189 190 case CanCmdPaneProvider.SEND_CURRENT_INTERVAL: 191 intervalSpinner.setValue(value); 192 break; 193 194 case CanCmdPaneProvider.SOD_DELAY: 195 sodDelaySpinner.setValue(value); 196 break; 197 198 case CanCmdPaneProvider.UNUSED_NV10: 199 case CanCmdPaneProvider.UNUSED_NV15: 200 case CanCmdPaneProvider.UNUSED_NV16: 201 // Not currently used on CANCMD 202 break; 203 204 default: 205 // Not used, or row was -1 206// log.debug("Update unknown NV {}", nv); 207 } 208 } 209 } 210 211 /** 212 * Update the command station number 213 */ 214 protected class UpdateCmdStaNo implements UpdateNV { 215 216 /** {@inheritDoc} */ 217 @Override 218 public void setNewVal(int index) { 219 int cmdStaNo = cmdStaNoSpinner.getIntegerValue(); 220 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 221 _dataModel.setValueAt(cmdStaNo, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 222 } 223 } 224 225 /** 226 * Update the Flags 227 */ 228 protected class UpdateFlags implements UpdateNV { 229 230 /** {@inheritDoc} */ 231 @Override 232 public void setNewVal(int index) { 233 int flags = csFlags[index].getFlags(); 234 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 235 _dataModel.setValueAt(flags, csFlags[index].getNv() - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 236 } 237 } 238 239 /** 240 * Update a current Limit 241 */ 242 protected class UpdateCurrentLimit implements UpdateNV { 243 244 /** {@inheritDoc} */ 245 @Override 246 public void setNewVal(int index) { 247 // CANCMD current limits are raw A/D values ( 0 - 255 ), the current in mA 248 // is the raw value multiplied by the current multiplier NV, so no scaling here. 249 int limit; 250 if (index == CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT) { 251 limit = mainSpinner.getIntegerValue(); 252 } else { 253 limit = progSpinner.getIntegerValue(); 254 } 255 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 256 _dataModel.setValueAt(limit, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 257 } 258 } 259 260 /** 261 * Update the Node Number of events to be mapped to DCC accessory commands 262 */ 263 protected class UpdateNnMap implements UpdateNV { 264 265 /** {@inheritDoc} */ 266 @Override 267 public void setNewVal(int index) { 268 int mapNn = nnMapDccSpinner.getIntegerValue(); 269 int mapNnHi = mapNn/256; 270 int mapNnLo = mapNn%256; 271 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 272 _dataModel.setValueAt(mapNnHi, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 273 _dataModel.setValueAt(mapNnLo, index, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 274 } 275 } 276 277 protected class UpdateSodDelay implements UpdateNV { 278 279 /** {@inheritDoc} */ 280 @Override 281 public void setNewVal(int index) { 282 int sodDelay = sodDelaySpinner.getIntegerValue(); 283 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 284 _dataModel.setValueAt(sodDelay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 285 } 286 } 287 288 protected class UpdateInterval implements UpdateNV { 289 290 /** {@inheritDoc} */ 291 @Override 292 public void setNewVal(int index) { 293 int interval = intervalSpinner.getIntegerValue(); 294 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 295 _dataModel.setValueAt(interval, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 296 } 297 } 298 299 protected class UpdateAck implements UpdateNV { 300 301 /** {@inheritDoc} */ 302 @Override 303 public void setNewVal(int index) { 304 int ack = ackSpinner.getIntegerValue(); 305 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 306 _dataModel.setValueAt(ack, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 307 } 308 } 309 310 protected class UpdateMult implements UpdateNV { 311 312 /** {@inheritDoc} */ 313 @Override 314 public void setNewVal(int index) { 315 int mult = multSpinner.getIntegerValue(); 316 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 317 _dataModel.setValueAt(mult, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 318 } 319 } 320 321 protected class UpdateWalkabout implements UpdateNV { 322 323 /** {@inheritDoc} */ 324 @Override 325 public void setNewVal(int index) { 326 int delay = walkaboutSpinner.getIntegerValue(); 327 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 328 _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 329 } 330 } 331 332 public class CmdStaPane extends JPanel { 333 334 /** 335 * Panel to display command station NVs 336 */ 337 public CmdStaPane() { 338 super(); 339 340 JPanel gridPane = new JPanel(new GridBagLayout()); 341 JPanel [] flagPane = new JPanel[3]; 342 GridBagConstraints c = new GridBagConstraints(); 343 c.fill = GridBagConstraints.HORIZONTAL; 344 345 for (int i = 0; i < 3; i++) { 346 csFlags[i] = new CmdStaFlags(i, CanCmdPaneProvider.USER_FLAGS + i, flagTitleStrings[i], flagStrings[i], flagTtStrings[i], flagUpdateFn); 347 csFlags[i].setFlags(getSelectValue8(CanCmdPaneProvider.USER_FLAGS + i)); 348 flagPane[i] = csFlags[i].getContents(); 349 } 350 351 c.weightx = 1; 352 c.weighty = 1; 353 c.gridx = 0; 354 c.gridy = 0; 355 356 // x = 1 357 cmdStaNoSpinner = new TitledSpinner(Bundle.getMessage("CmdStaNo"), CanCmdPaneProvider.CMD_STATION_NUMBER, cmdStaNoUpdateFn); 358 cmdStaNoSpinner.setToolTip(Bundle.getMessage("CmdStaNoTt")); 359 cmdStaNoSpinner.init(0, 0, 255, 1); 360 gridPane.add(cmdStaNoSpinner, c); 361 c.gridy++; 362 363 walkaboutSpinner = new TitledSpinner(Bundle.getMessage("WalkaboutTimeout"), CanCmdPaneProvider.WALKABOUT_TIMEOUT, walkaboutUpdateFn); 364 walkaboutSpinner.setToolTip(Bundle.getMessage("WalkaboutTimeoutTt")); 365 walkaboutSpinner.init(getSelectValue8(CanCmdPaneProvider.WALKABOUT_TIMEOUT, 1), 1, 255, 1); 366 gridPane.add(walkaboutSpinner, c); 367 c.gridy++; 368 369 multSpinner = new TitledSpinner(Bundle.getMessage("CurrentMultiplier"), CanCmdPaneProvider.CURRENT_MULTIPLIER, multUpdateFn); 370 multSpinner.setToolTip(Bundle.getMessage("CurrentMultiplierTt")); 371 multSpinner.init(getSelectValue8(CanCmdPaneProvider.CURRENT_MULTIPLIER, 1), 1, 255, 1); 372 gridPane.add(multSpinner, c); 373 c.gridy++; 374 375 ackSpinner = new TitledSpinner(Bundle.getMessage("IncCurrentForAck"), CanCmdPaneProvider.INC_CURRENT_FOR_ACK, ackUpdateFn); 376 ackSpinner.setToolTip(Bundle.getMessage("IncCurrentForAckTt")); 377 ackSpinner.init(getSelectValue8(CanCmdPaneProvider.INC_CURRENT_FOR_ACK, 1), 1, 255, 1); 378 gridPane.add(ackSpinner, c); 379 c.gridy++; 380 381 intervalSpinner = new TitledSpinner(Bundle.getMessage("SendCurrentInterval"), CanCmdPaneProvider.SEND_CURRENT_INTERVAL, intervalUpdateFn); 382 intervalSpinner.setToolTip(Bundle.getMessage("SendCurrentIntervalTt")); 383 intervalSpinner.init(getSelectValue8(CanCmdPaneProvider.SEND_CURRENT_INTERVAL), 0, 255, 1); 384 gridPane.add(intervalSpinner, c); 385 c.gridy++; 386 387 c.gridwidth = 3; 388 389 mainSpinner = new TitledSpinner(Bundle.getMessage("CanCmdMainLimit"), CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT, currentLimitUpdateFn); 390 mainSpinner.setToolTip(Bundle.getMessage("CanCmdMainLimitTt")); 391 mainSpinner.init(getSelectValue8(CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT, 1), 1, 255, 1); 392 gridPane.add(mainSpinner, c); 393 c.gridy++; 394 395 progSpinner = new TitledSpinner(Bundle.getMessage("CanCmdProgLimit"), CanCmdPaneProvider.PROG_TRACK_CURRENT_LIMIT, currentLimitUpdateFn); 396 progSpinner.setToolTip(Bundle.getMessage("CanCmdProgLimitTt")); 397 progSpinner.init(getSelectValue8(CanCmdPaneProvider.PROG_TRACK_CURRENT_LIMIT, 1), 1, 255, 1); 398 gridPane.add(progSpinner, c); 399 c.gridy++; 400 c.gridx = 0; 401 402 gridPane.add(flagPane[USER_FLAGS], c); 403 c.gridx++; 404 405 gridPane.add(flagPane[OPS_FLAGS], c); 406 c.gridx++; 407 408 gridPane.add(flagPane[DEBUG_FLAGS], c); 409 c.gridx++; 410 411 add(gridPane); 412 } 413 } 414 415 /** 416 * Panel to display DCC related NVs 417 */ 418 public class DccPane extends JPanel { 419 public DccPane() { 420 super(); 421 422 JPanel gridPane = new JPanel(new GridBagLayout()); 423 GridBagConstraints c = new GridBagConstraints(); 424 c.fill = GridBagConstraints.HORIZONTAL; 425 426 c.weightx = 1; 427 c.weighty = 1; 428 c.gridx = 0; 429 c.gridy = 0; 430 431 c.gridy++; 432 433 nnMapDccSpinner = new TitledSpinner(Bundle.getMessage("NnMapDcc"), CanCmdPaneProvider.NN_MAP_DCC_HI, nnMapUpdateFn); 434 nnMapDccSpinner.setToolTip(Bundle.getMessage("NnMapDccTt")); 435 int nn = getSelectValue16(CanCmdPaneProvider.NN_MAP_DCC_HI, CanCmdPaneProvider.NN_MAP_DCC_LO, CanCmdPaneProvider.MIN_NN, CanCmdPaneProvider.MAX_NN); 436 nnMapDccSpinner.init(nn, 0, 65535, 1); 437 gridPane.add(nnMapDccSpinner, c); 438 c.gridy++; 439 440 gridPane.add(nnMapDccSpinner, c); 441 c.gridy++; 442 443 add(gridPane); 444 } 445 } 446 447 /** 448 * Panel to display CBUS operation related NVs 449 */ 450 public class CbusPane extends JPanel { 451 public CbusPane() { 452 super(); 453 454 JPanel gridPane = new JPanel(new GridBagLayout()); 455 GridBagConstraints c = new GridBagConstraints(); 456 c.fill = GridBagConstraints.HORIZONTAL; 457 458 c.weightx = 1; 459 c.weighty = 1; 460 c.gridx = 0; 461 c.gridy = 0; 462 463 sodDelaySpinner = new TitledSpinner(Bundle.getMessage("SodDelay"), CanCmdPaneProvider.SOD_DELAY, sodDelayUpdateFn); 464 sodDelaySpinner.setToolTip(Bundle.getMessage("SodDelayTt")); 465 sodDelaySpinner.init(getSelectValue8(CanCmdPaneProvider.SOD_DELAY), 0, 255, 1); 466 gridPane.add(sodDelaySpinner, c); 467 c.gridy++; 468 469 add(gridPane); 470 } 471 } 472 473 //private static final Logger log = LoggerFactory.getLogger(CanCmdEditNVPane.class); 474 475}