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 int limit; 248 double fLimit; 249 if (index == CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT) { 250 fLimit = mainSpinner.getDoubleValue(); 251 } else { 252 fLimit = progSpinner.getDoubleValue(); 253 } 254 // Limit to 10mA precision 255 limit = (int)(fLimit*100 + 0.5); 256 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 257 _dataModel.setValueAt(limit, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 258 } 259 } 260 261 /** 262 * Update the Node Number of events to be mapped to DCC accessory commands 263 */ 264 protected class UpdateNnMap implements UpdateNV { 265 266 /** {@inheritDoc} */ 267 @Override 268 public void setNewVal(int index) { 269 int mapNn = nnMapDccSpinner.getIntegerValue(); 270 int mapNnHi = mapNn/256; 271 int mapNnLo = mapNn%256; 272 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 273 _dataModel.setValueAt(mapNnHi, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 274 _dataModel.setValueAt(mapNnLo, index, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 275 } 276 } 277 278 protected class UpdateSodDelay implements UpdateNV { 279 280 /** {@inheritDoc} */ 281 @Override 282 public void setNewVal(int index) { 283 int sodDelay = sodDelaySpinner.getIntegerValue(); 284 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 285 _dataModel.setValueAt(sodDelay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 286 } 287 } 288 289 protected class UpdateInterval implements UpdateNV { 290 291 /** {@inheritDoc} */ 292 @Override 293 public void setNewVal(int index) { 294 int interval = intervalSpinner.getIntegerValue(); 295 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 296 _dataModel.setValueAt(interval, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 297 } 298 } 299 300 protected class UpdateAck implements UpdateNV { 301 302 /** {@inheritDoc} */ 303 @Override 304 public void setNewVal(int index) { 305 int ack = ackSpinner.getIntegerValue(); 306 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 307 _dataModel.setValueAt(ack, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 308 } 309 } 310 311 protected class UpdateMult implements UpdateNV { 312 313 /** {@inheritDoc} */ 314 @Override 315 public void setNewVal(int index) { 316 int mult = multSpinner.getIntegerValue(); 317 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 318 _dataModel.setValueAt(mult, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 319 } 320 } 321 322 protected class UpdateWalkabout implements UpdateNV { 323 324 /** {@inheritDoc} */ 325 @Override 326 public void setNewVal(int index) { 327 int delay = multSpinner.getIntegerValue(); 328 // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc 329 _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 330 } 331 } 332 333 public class CmdStaPane extends JPanel { 334 335 /** 336 * Panel to display command station NVs 337 */ 338 public CmdStaPane() { 339 super(); 340 341 JPanel gridPane = new JPanel(new GridBagLayout()); 342 JPanel [] flagPane = new JPanel[3]; 343 GridBagConstraints c = new GridBagConstraints(); 344 c.fill = GridBagConstraints.HORIZONTAL; 345 346 for (int i = 0; i < 3; i++) { 347 csFlags[i] = new CmdStaFlags(i, CanCmdPaneProvider.USER_FLAGS + i, flagTitleStrings[i], flagStrings[i], flagTtStrings[i], flagUpdateFn); 348 csFlags[i].setFlags(getSelectValue8(CanCmdPaneProvider.USER_FLAGS + i)); 349 flagPane[i] = csFlags[i].getContents(); 350 } 351 352 c.weightx = 1; 353 c.weighty = 1; 354 c.gridx = 0; 355 c.gridy = 0; 356 357 // x = 1 358 cmdStaNoSpinner = new TitledSpinner(Bundle.getMessage("CmdStaNo"), CanCmdPaneProvider.CMD_STATION_NUMBER, cmdStaNoUpdateFn); 359 cmdStaNoSpinner.setToolTip(Bundle.getMessage("CmdStaNoTt")); 360 cmdStaNoSpinner.init(0, 0, 255, 1); 361 gridPane.add(cmdStaNoSpinner, c); 362 c.gridy++; 363 364 walkaboutSpinner = new TitledSpinner(Bundle.getMessage("WalkaboutTimeout"), CanCmdPaneProvider.WALKABOUT_TIMEOUT, walkaboutUpdateFn); 365 walkaboutSpinner.setToolTip(Bundle.getMessage("WalkaboutTimeoutTt")); 366 walkaboutSpinner.init(getSelectValue8(CanCmdPaneProvider.WALKABOUT_TIMEOUT, 1), 1, 60, 255); 367 gridPane.add(walkaboutSpinner, c); 368 c.gridy++; 369 370 multSpinner = new TitledSpinner(Bundle.getMessage("CurrentMultiplier"), CanCmdPaneProvider.CURRENT_MULTIPLIER, multUpdateFn); 371 multSpinner.setToolTip(Bundle.getMessage("CurrentMultiplierTt")); 372 multSpinner.init(getSelectValue8(CanCmdPaneProvider.CURRENT_MULTIPLIER, 1), 1, 10, 255); 373 gridPane.add(multSpinner, c); 374 c.gridy++; 375 376 ackSpinner = new TitledSpinner(Bundle.getMessage("IncCurrentForAck"), CanCmdPaneProvider.INC_CURRENT_FOR_ACK, ackUpdateFn); 377 ackSpinner.setToolTip(Bundle.getMessage("IncCurrentForAckTt")); 378 ackSpinner.init(getSelectValue8(CanCmdPaneProvider.INC_CURRENT_FOR_ACK, 1), 1, 3, 255); 379 gridPane.add(ackSpinner, c); 380 c.gridy++; 381 382 intervalSpinner = new TitledSpinner(Bundle.getMessage("SendCurrentInterval"), CanCmdPaneProvider.SEND_CURRENT_INTERVAL, intervalUpdateFn); 383 intervalSpinner.setToolTip(Bundle.getMessage("SendCurrentIntervalTt")); 384 intervalSpinner.init(getSelectValue8(CanCmdPaneProvider.SEND_CURRENT_INTERVAL), 0, 255, 1); 385 gridPane.add(intervalSpinner, c); 386 c.gridy++; 387 388 c.gridwidth = 3; 389 390 mainSpinner = new TitledSpinner(Bundle.getMessage("MainLimit"), CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT, currentLimitUpdateFn); 391 mainSpinner.setToolTip(Bundle.getMessage("MainLimitTt")); 392 mainSpinner.init(getSelectValue8(CanCmdPaneProvider.MAIN_TRACK_CURRENT_LIMIT, 1), 1.0, 96.0, 255.0); 393 gridPane.add(mainSpinner, c); 394 c.gridy++; 395 396 progSpinner = new TitledSpinner(Bundle.getMessage("ProgLimit"), CanCmdPaneProvider.PROG_TRACK_CURRENT_LIMIT, currentLimitUpdateFn); 397 progSpinner.setToolTip(Bundle.getMessage("ProgLimitTt")); 398 progSpinner.init(getSelectValue8(CanCmdPaneProvider.PROG_TRACK_CURRENT_LIMIT, 1), 1.0, 96.0, 255.0); 399 gridPane.add(progSpinner, c); 400 c.gridy++; 401 c.gridx = 0; 402 403 gridPane.add(flagPane[USER_FLAGS], c); 404 c.gridx++; 405 406 gridPane.add(flagPane[OPS_FLAGS], c); 407 c.gridx++; 408 409 gridPane.add(flagPane[DEBUG_FLAGS], c); 410 c.gridx++; 411 412 add(gridPane); 413 } 414 } 415 416 /** 417 * Panel to display DCC related NVs 418 */ 419 public class DccPane extends JPanel { 420 public DccPane() { 421 super(); 422 423 JPanel gridPane = new JPanel(new GridBagLayout()); 424 GridBagConstraints c = new GridBagConstraints(); 425 c.fill = GridBagConstraints.HORIZONTAL; 426 427 c.weightx = 1; 428 c.weighty = 1; 429 c.gridx = 0; 430 c.gridy = 0; 431 432 c.gridy++; 433 434 nnMapDccSpinner = new TitledSpinner(Bundle.getMessage("NnMapDcc"), CanCmdPaneProvider.NN_MAP_DCC_HI, nnMapUpdateFn); 435 nnMapDccSpinner.setToolTip(Bundle.getMessage("NnMapDccTt")); 436 int nn = getSelectValue16(CanCmdPaneProvider.NN_MAP_DCC_HI, CanCmdPaneProvider.NN_MAP_DCC_LO, CanCmdPaneProvider.MIN_NN, CanCmdPaneProvider.MAX_NN); 437 nnMapDccSpinner.init(nn, 0, 65535, 1); 438 gridPane.add(nnMapDccSpinner, c); 439 c.gridy++; 440 441 gridPane.add(nnMapDccSpinner, c); 442 c.gridy++; 443 444 add(gridPane); 445 } 446 } 447 448 /** 449 * Panel to display CBUS operation related NVs 450 */ 451 public class CbusPane extends JPanel { 452 public CbusPane() { 453 super(); 454 455 JPanel gridPane = new JPanel(new GridBagLayout()); 456 GridBagConstraints c = new GridBagConstraints(); 457 c.fill = GridBagConstraints.HORIZONTAL; 458 459 c.weightx = 1; 460 c.weighty = 1; 461 c.gridx = 0; 462 c.gridy = 0; 463 464 sodDelaySpinner = new TitledSpinner(Bundle.getMessage("SodDelay"), CanCmdPaneProvider.SOD_DELAY, sodDelayUpdateFn); 465 sodDelaySpinner.setToolTip(Bundle.getMessage("SodDelayTt")); 466 sodDelaySpinner.init(getSelectValue8(CanCmdPaneProvider.SOD_DELAY), 0, 255, 1); 467 gridPane.add(sodDelaySpinner, c); 468 c.gridy++; 469 470 add(gridPane); 471 } 472 } 473 474 //private final static Logger log = LoggerFactory.getLogger(CanCmdEditNVPane.class); 475 476}