001package jmri.jmrit.beantable; 002 003import com.alexandriasoftware.swing.Validation; 004 005import java.awt.*; 006import java.awt.event.ActionEvent; 007import java.beans.PropertyChangeListener; 008import java.util.Objects; 009 010import javax.annotation.Nonnull; 011import javax.swing.*; 012import javax.swing.border.Border; 013 014import jmri.*; 015import jmri.jmrit.beantable.light.LightControlPane; 016import jmri.jmrit.beantable.light.LightIntensityPane; 017import jmri.jmrit.beantable.light.LightTableDataModel; 018import jmri.NamedBean.DisplayOptions; 019import jmri.swing.ManagerComboBox; 020import jmri.swing.SystemNameValidator; 021import jmri.util.JmriJFrame; 022import jmri.util.swing.JmriJOptionPane; 023 024/** 025 * Swing action to create and register a LightTable GUI. 026 * <p> 027 * Based on SignalHeadTableAction.java 028 * 029 * @author Dave Duchamp Copyright (C) 2004 030 * @author Egbert Broerse Copyright (C) 2017 031 */ 032public class LightTableAction extends AbstractTableAction<Light> { 033 034 /** 035 * Create an action with a specific title. 036 * <p> 037 * Note that the argument is the Action title, not the title of the 038 * resulting frame. Perhaps this should be changed? 039 * 040 * @param s title of the action 041 */ 042 public LightTableAction(String s) { 043 super(s); 044 // disable ourself if there is no primary Light manager available 045 if (lightManager == null) { 046 super.setEnabled(false); 047 } 048 } 049 050 public LightTableAction() { 051 this(Bundle.getMessage("TitleLightTable")); 052 } 053 054 protected LightManager lightManager = InstanceManager.getNullableDefault(jmri.LightManager.class); 055 056 /** 057 * {@inheritDoc} 058 */ 059 @Override 060 public void setManager(@Nonnull Manager<Light> man) { 061 if (man instanceof LightManager) { 062 lightManager = (LightManager) man; 063 } 064 } 065 066 /** 067 * Create the JTable DataModel, along with the changes for the specific case 068 * of Lights. 069 */ 070 @Override 071 protected void createModel() { 072 m = new LightTableDataModel(lightManager); 073 } 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 protected void setTitle() { 080 f.setTitle(Bundle.getMessage("TitleLightTable")); 081 } 082 083 /** 084 * {@inheritDoc} 085 */ 086 @Override 087 protected String helpTarget() { 088 return "package.jmri.jmrit.beantable.LightTable"; 089 } 090 091 JmriJFrame addFrame = null; 092 Light curLight = null; 093 boolean lightCreatedOrUpdated = false; 094 boolean noWarn = false; 095 096 // items for Add/Edit Light frame 097 JLabel systemLabel = new JLabel(Bundle.getMessage("SystemConnectionLabel")); 098 ManagerComboBox<Light> prefixBox = new ManagerComboBox<>(); 099 JCheckBox addRangeBox = new JCheckBox(Bundle.getMessage("AddRangeBox")); 100 JTextField hardwareAddressTextField = new JTextField(10); 101 SystemNameValidator hardwareAddressValidator; 102 SpinnerNumberModel rangeSpinner = new SpinnerNumberModel(1, 1, 50, 1); // maximum 50 items 103 JSpinner numberToAdd = new JSpinner(rangeSpinner); 104 JLabel labelNumToAdd = new JLabel(" " + Bundle.getMessage("LabelNumberToAdd")); 105 String systemSelectionCombo = this.getClass().getName() + ".SystemSelected"; 106 107 JLabel systemNameLabel = new JLabel(Bundle.getMessage("LabelSystemName") + " "); 108 JTextField userName = new JTextField(20); 109 JLabel userNameLabel = new JLabel(Bundle.getMessage("LabelUserName") + " "); 110 JButton create; 111 JButton cancel = new JButton(Bundle.getMessage("ButtonCancel")); 112 PropertyChangeListener colorChangeListener; 113 114 JLabel status1 = new JLabel(Bundle.getMessage("LightCreateInst")); 115 JLabel status2 = new JLabel(""); 116 Manager<Light> connectionChoice = null; 117 private LightIntensityPane lightIntensityPanel; 118 private LightControlPane lightControlPanel; 119 120 private boolean checkEnabled = jmri.InstanceManager.getDefault(jmri.configurexml.ShutdownPreferences.class).isStoreCheckEnabled(); 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 protected void addPressed(ActionEvent e) { 127 cancelPressed(null); 128 129 if (addFrame == null) { 130 addFrame = new JmriJFrame(Bundle.getMessage("TitleAddLight"), false, true); 131 addFrame.addHelpMenu("package.jmri.jmrit.beantable.LightAddEdit", true); 132 addFrame.setLocation(100, 30); 133 Container contentPane = addFrame.getContentPane(); 134 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 135 JPanel panel1 = new JPanel(); 136 panel1.setLayout(new FlowLayout()); 137 configureManagerComboBox(prefixBox, lightManager, LightManager.class); 138 panel1.add(systemLabel); 139 panel1.add(prefixBox); 140 panel1.add(new JLabel(" ")); 141 panel1.add(addRangeBox); 142 addRangeBox.setVisible(true); // reset after Edit Light 143 addRangeBox.setToolTipText(Bundle.getMessage("LightAddRangeHint")); 144 addRangeBox.addActionListener((ActionEvent e1) -> addRangeChanged()); 145 panel1.add(systemNameLabel); 146 systemNameLabel.setVisible(false); 147 prefixBox.setToolTipText(Bundle.getMessage("LightSystemHint")); 148 prefixBox.addActionListener((ActionEvent e1) -> prefixChanged()); 149 contentPane.add(panel1); 150 JPanel hardwareAddressPanel = new JPanel(); 151 hardwareAddressPanel.setLayout(new FlowLayout()); 152 hardwareAddressPanel.add(new JLabel(Bundle.getMessage("LabelHardwareAddress"))); 153 hardwareAddressPanel.add(hardwareAddressTextField); 154 hardwareAddressTextField.setText(""); // reset from possible previous use 155 hardwareAddressTextField.setToolTipText(Bundle.getMessage("LightHardwareAddressHint")); 156 hardwareAddressTextField.setName("hwAddressTextField"); // for GUI test NOI18N 157 158 if (hardwareAddressValidator==null){ 159 hardwareAddressValidator = new SystemNameValidator(hardwareAddressTextField, Objects.requireNonNull(prefixBox.getSelectedItem()), true); 160 } else { 161 hardwareAddressValidator.setManager(prefixBox.getSelectedItem()); 162 } 163 164 hardwareAddressTextField.setInputVerifier(hardwareAddressValidator); 165 prefixBox.addActionListener((evt) -> hardwareAddressValidator.setManager(prefixBox.getSelectedItem())); 166 hardwareAddressValidator.addPropertyChangeListener("validation", (evt) -> { // NOI18N 167 Validation validation = hardwareAddressValidator.getValidation(); 168 Validation.Type type = validation.getType(); 169 create.setEnabled(type != Validation.Type.WARNING && type != Validation.Type.DANGER); 170 String message = validation.getMessage(); 171 if (message == null) { 172 status1.setText(""); 173 } else { 174 message = message.trim(); 175 if (message.startsWith("<html>") && message.contains("<br>")) { 176 message = message.substring(0, message.indexOf("<br>")); 177 if (!message.endsWith("</html>")) { 178 message = message + "</html>"; 179 } 180 } 181 status1.setText(message); 182 } 183 }); 184 // tooltip and entry mask for sysNameTextField will be assigned later by prefixChanged() 185 hardwareAddressPanel.add(labelNumToAdd); 186 hardwareAddressPanel.add(numberToAdd); 187 numberToAdd.setToolTipText(Bundle.getMessage("LightNumberToAddHint")); 188 contentPane.add(hardwareAddressPanel); 189 JPanel panel2 = new JPanel(); 190 panel2.setLayout(new FlowLayout()); 191 panel2.add(userNameLabel); 192 panel2.add(userName); 193 userName.setText(""); // reset from possible previous use 194 userName.setToolTipText(Bundle.getMessage("LightUserNameHint")); 195 userName.setName("userName"); // for GUI test NOI18N 196 prefixBox.setName("prefixBox"); // for GUI test NOI18N 197 contentPane.add(panel2); 198 lightIntensityPanel = new LightIntensityPane(false); 199 Border varPanelTitled = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), 200 Bundle.getMessage("LightVariableBorder")); 201 lightIntensityPanel.setBorder(varPanelTitled); 202 contentPane.add(lightIntensityPanel); 203 // light control table 204 lightControlPanel = new LightControlPane(); 205 Border panel3Titled = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), 206 Bundle.getMessage("LightControllerTitlePlural")); 207 lightControlPanel.setBorder(panel3Titled); 208 contentPane.add(lightControlPanel); 209 // message items 210 JPanel panel4 = new JPanel(); 211 panel4.setLayout(new BoxLayout(panel4, BoxLayout.Y_AXIS)); 212 JPanel panel41 = new JPanel(); 213 panel41.setLayout(new FlowLayout()); 214 // add status bar above buttons 215 panel41.add(status1); 216 status1.setText(Bundle.getMessage("LightCreateInst")); 217 status1.setFont(status1.getFont().deriveFont(0.9f * systemNameLabel.getFont().getSize())); // a bit smaller 218 status1.setForeground(Color.gray); 219 JPanel panel42 = new JPanel(); 220 panel42.setLayout(new FlowLayout()); 221 panel42.add(status2); 222 status2.setText(Bundle.getMessage("LightCreateInst")); 223 status2.setFont(status2.getFont().deriveFont(0.9f * systemNameLabel.getFont().getSize())); // a bit smaller 224 status2.setForeground(Color.gray); 225 status2.setText(""); 226 status2.setVisible(false); 227 panel4.add(panel41); 228 panel4.add(panel42); 229 contentPane.add(panel4); 230 // buttons at bottom of window 231 JPanel panel5 = new JPanel(); 232 panel5.setLayout(new FlowLayout(FlowLayout.TRAILING)); 233 panel5.add(cancel); 234 cancel.setText(Bundle.getMessage("ButtonCancel")); 235 cancel.addActionListener(this::cancelPressed); 236 cancel.setToolTipText(Bundle.getMessage("LightCancelButtonHint")); 237 panel5.add(create = new JButton(Bundle.getMessage("ButtonCreate"))); 238 create.addActionListener(this::createPressed); 239 create.setToolTipText(Bundle.getMessage("LightCreateButtonHint")); 240 create.setName("createButton"); // for GUI test NOI18N 241 create.setVisible(true); 242 contentPane.add(panel5); 243 hardwareAddressValidator.verify(hardwareAddressTextField); 244 } 245 prefixChanged(); 246 addFrame.addWindowListener(new java.awt.event.WindowAdapter() { 247 @Override 248 public void windowClosing(java.awt.event.WindowEvent e) { 249 cancelPressed(null); 250 } 251 }); 252 create.setEnabled(false); // start as disabled (false) until a valid entry is typed in 253 // reset statusBar text 254 status1.setText(Bundle.getMessage("LightCreateInst")); 255 status1.setForeground(Color.gray); 256 257 addFrame.setEscapeKeyClosesWindow(true); 258 addFrame.getRootPane().setDefaultButton(create); 259 260 addFrame.pack(); 261 addFrame.setVisible(true); 262 } 263 264 private String addEntryToolTip; 265 266 protected void prefixChanged() { 267 if (prefixBox.getSelectedItem() != null) { 268 lightIntensityPanel.setVisible(supportsVariableLights()); 269 // behaves like the AddNewHardwareDevice pane (dim if not available, do not hide) 270 addRangeBox.setEnabled(canAddRange()); 271 addRangeBox.setSelected(false); 272 numberToAdd.setValue(1); 273 numberToAdd.setEnabled(false); 274 labelNumToAdd.setEnabled(false); 275 // show tooltip for selected system connection 276 connectionChoice = prefixBox.getSelectedItem(); // store in Field for CheckedTextField 277 // Update tooltip in the Add Light pane to match system connection selected from combobox. 278 log.debug("Connection choice = [{}]", connectionChoice); 279 // get tooltip from ProxyLightManager 280 String systemPrefix = connectionChoice.getSystemPrefix(); 281 addEntryToolTip = connectionChoice.getEntryToolTip(); 282 addRangeBox.setEnabled(((LightManager) connectionChoice).allowMultipleAdditions(systemPrefix)); 283 log.debug("DefaultLightManager tip: {}", addEntryToolTip); 284 // show Hardware address field tooltip in the Add Light pane to match system connection selected from combobox 285 if (addEntryToolTip != null) { 286 hardwareAddressTextField.setToolTipText( 287 Bundle.getMessage("AddEntryToolTipLine1", 288 connectionChoice.getMemo().getUserName(), 289 Bundle.getMessage("Lights"), 290 addEntryToolTip)); 291 hardwareAddressValidator.setToolTipText(hardwareAddressTextField.getToolTipText()); 292 hardwareAddressValidator.verify(hardwareAddressTextField); 293 } 294 create.setEnabled(true); // too severe to start as disabled (false) until we fully support validation 295 addFrame.pack(); 296 addFrame.setVisible(true); 297 } 298 } 299 300 protected void addRangeChanged() { 301 numberToAdd.setEnabled(addRangeBox.isSelected()); 302 labelNumToAdd.setEnabled(addRangeBox.isSelected()); 303 } 304 305 /** 306 * Activate Add a range option if manager accepts adding more than 1 Light. 307 * TODO: Will only verify against formats which accept "11" as a Hardware address. 308 */ 309 private boolean canAddRange() { 310 String testSysName = Objects.requireNonNull(prefixBox.getSelectedItem()).getSystemPrefix() + "L11"; 311 return lightManager.allowMultipleAdditions(testSysName); 312 } 313 314 /** 315 * Check if LightManager supports variable Lights. 316 * TODO: Will only verify against formats which accept "11" as a Hardware address. 317 * 318 * @return true if system can support variable lights. 319 */ 320 boolean supportsVariableLights() { 321 String testSysName = Objects.requireNonNull(prefixBox.getSelectedItem()).getSystemPrefix() + "L11"; 322 return lightManager.supportsVariableLights(testSysName); 323 } 324 325 /** 326 * Create lights when the Create New button on the Add/Create pane is 327 * pressed and entry is valid. 328 * 329 * @param e the button press action 330 */ 331 void createPressed(ActionEvent e) { 332 333 status1.setForeground(Color.gray); // reset 334 status1.setText(""); 335 String lightPrefix = Objects.requireNonNull(prefixBox.getSelectedItem()).getSystemPrefix() + "L"; 336 String turnoutPrefix = prefixBox.getSelectedItem().getSystemPrefix() + "T"; 337 String curAddress = hardwareAddressTextField.getText(); 338 // first validation is provided by HardwareAddress ValidatedTextField on yield focus 339 if (curAddress.length() < 1) { 340 log.warn("Hardware Address was not entered"); 341 status1.setText(Bundle.getMessage("LightError17")); 342 status1.setForeground(Color.red); 343 status2.setVisible(false); 344 hardwareAddressTextField.setBackground(Color.red); 345 addFrame.pack(); 346 addFrame.setVisible(true); 347 return; 348 } else { 349 hardwareAddressTextField.setBackground(Color.white); 350 } 351 String suName = lightPrefix + curAddress; 352 String uName = userName.getText(); 353 if (uName.isEmpty()) { 354 uName = null; // a blank field means no user name 355 } 356 // Does System Name have a valid format? 357 if (InstanceManager.getDefault(LightManager.class).validSystemNameFormat(suName) != Manager.NameValidity.VALID) { 358 // Invalid System Name format 359 log.warn("Invalid Light system name format entered: {}", suName); 360 status1.setText(Bundle.getMessage("LightError3")); 361 status1.setForeground(Color.red); 362 status2.setText(Bundle.getMessage("LightError6")); 363 status2.setVisible(true); 364 hardwareAddressTextField.setBackground(Color.red); 365 addFrame.pack(); 366 addFrame.setVisible(true); 367 return; 368 } else { 369 hardwareAddressTextField.setBackground(Color.white); 370 } 371 // check if a Light with this name already exists 372 Light g = InstanceManager.getDefault(LightManager.class).getBySystemName(suName); 373 if (g != null) { 374 // Light already exists 375 status1.setText(Bundle.getMessage("LightError1")); 376 status1.setForeground(Color.red); 377 status2.setText(Bundle.getMessage("LightError2")); 378 status2.setVisible(true); 379 addFrame.pack(); 380 addFrame.setVisible(true); 381 return; 382 } 383 // check if Light exists under an alternate name if an alternate name exists 384 String altName = InstanceManager.getDefault(LightManager.class).convertSystemNameToAlternate(suName); 385 if (!altName.isEmpty()) { 386 g = InstanceManager.getDefault(LightManager.class).getBySystemName(altName); 387 if (g != null) { 388 // Light already exists 389 status1.setText(Bundle.getMessage("LightError10", altName)); 390 status1.setForeground(Color.red); 391 status2.setVisible(false); 392 addFrame.pack(); 393 addFrame.setVisible(true); 394 return; 395 } 396 } 397 // check if a Light with the same user name exists 398 if (uName != null) { 399 g = InstanceManager.getDefault(LightManager.class).getByUserName(uName); 400 if (g != null) { 401 // Light with this user name already exists 402 status1.setText(Bundle.getMessage("LightError8")); 403 status1.setForeground(Color.red); 404 status2.setText(Bundle.getMessage("LightError9")); 405 status2.setVisible(true); 406 addFrame.pack(); 407 addFrame.setVisible(true); 408 return; 409 } 410 } 411 // check if System Name corresponds to configured hardware 412 if (!InstanceManager.getDefault(LightManager.class).validSystemNameConfig(suName)) { 413 // System Name not in configured hardware 414 status1.setText(Bundle.getMessage("LightError5")); 415 status1.setForeground(Color.red); 416 status2.setText(Bundle.getMessage("LightError6")); 417 status2.setVisible(true); 418 addFrame.pack(); 419 addFrame.setVisible(true); 420 return; 421 } 422 // check if requested Light uses the same address as a Turnout 423 String testSN = turnoutPrefix + curAddress; 424 Turnout testT = InstanceManager.turnoutManagerInstance(). 425 getBySystemName(testSN); 426 if (testT != null) { 427 // Address (number) is already used as a Turnout 428 log.warn("Requested Light {} uses same address as Turnout {}", suName, testT); 429 if (!noWarn) { 430 int selectedValue = JmriJOptionPane.showOptionDialog(addFrame, 431 Bundle.getMessage("LightWarn5", suName, testSN), 432 Bundle.getMessage("WarningTitle"), 433 JmriJOptionPane.YES_NO_CANCEL_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, 434 new Object[]{Bundle.getMessage("ButtonYes"), Bundle.getMessage("ButtonYesPlus"), 435 Bundle.getMessage("ButtonNo")}, Bundle.getMessage("ButtonNo")); // default choice = No 436 if (selectedValue == 1) { 437 return; // return without creating on "No" response 438 } 439 if (selectedValue == 2) { 440 // Suppress future warnings, and continue 441 noWarn = true; 442 } 443 } 444 // Light with this system name address (number) already exists as a turnout 445 status2.setText(Bundle.getMessage("LightWarn4") + " " + testSN + "."); 446 status1.setForeground(Color.red); 447 status2.setVisible(true); 448 } 449 450 // Create a single new Light, or the first Light of a range 451 try { 452 g = InstanceManager.getDefault(LightManager.class).newLight(suName, uName); 453 } catch (IllegalArgumentException ex) { 454 // user input no good 455 handleCreateException(ex, suName); 456 return; // without creating 457 } 458 lightControlPanel.setLightFromControlTable(g); 459 if (g instanceof VariableLight) { 460 lightIntensityPanel.setLightFromPane((VariableLight)g); 461 } 462 g.activateLight(); 463 lightCreatedOrUpdated = true; 464 465 status2.setText(""); 466 status2.setVisible(false); 467 468 // provide feedback to user 469 String feedback = Bundle.getMessage("LightCreateFeedback") + " " + g.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME); 470 471 // create additional lights if requested 472 int numberOfLights = 1; 473 if ((InstanceManager.getDefault(LightManager.class).allowMultipleAdditions(suName)) 474 && addRangeBox.isSelected()) { 475 // get number requested 476 numberOfLights = (Integer) numberToAdd.getValue(); 477 } 478 if (numberOfLights > 1) { 479 for (int i = 1; i < numberOfLights; i++) { 480 481 try { 482 // bump system name 483 suName = InstanceManager.getDefault(LightManager.class).getNextValidSystemName(g); 484 485 // create it 486 g = lightManager.newLight(suName, uName); 487 log.debug("Light {} created",g); 488 // set up this light the same as the first light 489 lightControlPanel.setLightFromControlTable(g); 490 if (g instanceof VariableLight) { 491 lightIntensityPanel.setLightFromPane((VariableLight)g); 492 } 493 } catch (IllegalArgumentException | JmriException ex) { 494 // user input no good 495 handleCreateException(ex, suName); 496 return; // without creating any more Lights 497 } 498 } 499 feedback = feedback + " - " + suName + ", " + uName; 500 } 501 create.setEnabled(false); 502 status1.setText(feedback); 503 status1.setForeground(Color.gray); 504 cancel.setText(Bundle.getMessage("ButtonClose")); // when Create/Apply has been clicked at least once, this is not Revert/Cancel 505 addFrame.pack(); 506 addFrame.setVisible(true); 507 } 508 509 void handleCreateException(Exception ex, String sysName) { 510 status1.setText(ex.getLocalizedMessage()); 511 String err = Bundle.getMessage("ErrorBeanCreateFailed", 512 InstanceManager.getDefault(LightManager.class).getBeanTypeHandled(),sysName); 513 JmriJOptionPane.showMessageDialog(addFrame, err + "\n" + ex.getLocalizedMessage(), 514 err, JmriJOptionPane.ERROR_MESSAGE); 515 } 516 517 /** 518 * Respond to the Cancel/Close button on the Add/Edit Light pane. 519 * 520 * @param e the button press action 521 */ 522 void cancelPressed(ActionEvent e) { 523 524 if (addFrame != null) { 525 addFrame.setVisible(false); // hide first for cleaner display 526 } 527 528 // remind to save, if Light was created or edited 529 if (lightCreatedOrUpdated && !checkEnabled) { 530 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 531 showInfoMessage(Bundle.getMessage("ReminderTitle"), Bundle.getMessage("ReminderSaveString", 532 Bundle.getMessage("MenuItemLightTable")), 533 getClassName(), 534 "remindSaveLight"); // NOI18N 535 } 536 lightCreatedOrUpdated = false; 537 // finally, get rid of the add/edit Frame 538 if (addFrame != null) { 539 540 lightControlPanel.dispose(); // closes any popup windows 541 542 removePrefixBoxListener(prefixBox); 543 InstanceManager.getDefault(UserPreferencesManager.class).setComboBoxLastSelection(systemSelectionCombo, prefixBox.getSelectedItem().getMemo().getUserName()); // store user pref 544 addFrame.dispose(); 545 addFrame = null; 546 create.removePropertyChangeListener(colorChangeListener); 547 548 } 549 } 550 551 // TODO: Move the next few static String methods to more appropriate place. 552 // LightControl.java ? Multiple Bundle property files will need changing. 553 554 public static String lightControlTitle = Bundle.getMessage("LightControlBorder"); 555 556 /** 557 * Get the description of the type of Light Control. 558 * 559 * @param lc the light control 560 * @param type the type of lc 561 * @return description of the type of lc or an empty string if type is not 562 * recognized 563 */ 564 public static String getDescriptionText(LightControl lc, int type) { 565 switch (type) { 566 case Light.SENSOR_CONTROL: 567 return java.text.MessageFormat.format(Bundle.getMessage("LightSensorControlDes"), lc.getControlSensorName(), getControlSensorSenseText(lc)); 568 case Light.FAST_CLOCK_CONTROL: 569 return java.text.MessageFormat.format(Bundle.getMessage("LightFastClockDes"), 570 // build 00:00 from 2 fields 571 String.format("%02d:%02d", lc.getFastClockOnHour(), lc.getFastClockOnMin()), String.format("%02d:%02d", lc.getFastClockOffHour(), lc.getFastClockOffMin())); 572 case Light.TURNOUT_STATUS_CONTROL: 573 return java.text.MessageFormat.format(Bundle.getMessage("LightTurnoutControlDes"), lc.getControlTurnoutName(), getControlTurnoutStateText(lc)); 574 case Light.TIMED_ON_CONTROL: 575 return java.text.MessageFormat.format(Bundle.getMessage("LightTimedOnControlDes"), "" + lc.getTimedOnDuration(), lc.getControlTimedOnSensorName(), getControlSensorSenseText(lc)); 576 case Light.TWO_SENSOR_CONTROL: 577 return java.text.MessageFormat.format(Bundle.getMessage("LightTwoSensorControlDes"), lc.getControlSensorName(), lc.getControlSensor2Name(), getControlSensorSenseText(lc)); 578 default: 579 return ""; 580 } 581 } 582 583 private static String getControlSensorSenseText(LightControl lc) { 584 if (lc.getControlSensorSense() == Sensor.ACTIVE) { 585 return Bundle.getMessage("SensorStateActive"); 586 } 587 return Bundle.getMessage("SensorStateInactive"); 588 } 589 590 private static String getControlTurnoutStateText(LightControl lc) { 591 if (lc.getControlTurnoutState() == Turnout.CLOSED) { 592 return InstanceManager.turnoutManagerInstance().getClosedText(); 593 } 594 return InstanceManager.turnoutManagerInstance().getThrownText(); 595 } 596 597 /** 598 * Validates that a physical turnout exists. 599 * 600 * @param inTurnoutName the (system or user) name of the turnout 601 * @param inOpenPane the pane over which to show dialogs (null to 602 * suppress dialogs) 603 * @return true if valid turnout was entered, false otherwise 604 */ 605 public boolean validatePhysicalTurnout(String inTurnoutName, Component inOpenPane) { 606 //check if turnout name was entered 607 if (inTurnoutName.isEmpty()) { 608 //no turnout entered 609 log.debug("no turnout was selected"); 610 return false; 611 } 612 //check that the turnout name corresponds to a defined physical turnout 613 Turnout t = InstanceManager.turnoutManagerInstance().getTurnout(inTurnoutName); 614 if (t == null) { 615 //There is no turnout corresponding to this name 616 if (inOpenPane != null) { 617 JmriJOptionPane.showMessageDialog(inOpenPane, 618 java.text.MessageFormat.format(Bundle.getMessage("LightWarn2"), inTurnoutName), 619 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 620 } 621 return false; 622 } 623 log.debug("validatePhysicalTurnout('{}')", inTurnoutName); 624 return true; 625 } 626 627 /** 628 * {@inheritDoc} 629 */ 630 @Override 631 public String getClassDescription() { 632 return Bundle.getMessage("TitleLightTable"); 633 } 634 635 /** 636 * {@inheritDoc} 637 */ 638 @Override 639 public void setMessagePreferencesDetails() { 640 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 641 setPreferenceItemDetails(getClassName(), "remindSaveLight", Bundle.getMessage("HideSaveReminder")); // NOI18N 642 super.setMessagePreferencesDetails(); 643 } 644 645 /** 646 * {@inheritDoc} 647 */ 648 @Override 649 protected String getClassName() { 650 return LightTableAction.class.getName(); 651 } 652 653 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LightTableAction.class); 654 655}