001package jmri.jmrit.display.controlPanelEditor; 002 003import java.awt.Dimension; 004import java.awt.FlowLayout; 005import java.awt.event.ActionEvent; 006import java.beans.PropertyChangeEvent; 007import java.beans.PropertyChangeListener; 008 009import javax.swing.Box; 010import javax.swing.BoxLayout; 011import javax.swing.JButton; 012import javax.swing.JLabel; 013import javax.swing.JPanel; 014import javax.swing.JTextField; 015 016import jmri.InstanceManager; 017import jmri.Sensor; 018import jmri.NamedBean.DisplayOptions; 019import jmri.jmrit.display.IndicatorTrack; 020import jmri.jmrit.display.IndicatorTrackIcon; 021import jmri.jmrit.display.IndicatorTurnoutIcon; 022import jmri.jmrit.display.Positionable; 023import jmri.jmrit.display.ToolTip; 024import jmri.jmrit.display.TurnoutIcon; 025import jmri.jmrit.logix.OBlock; 026import jmri.jmrit.logix.OBlockManager; 027import jmri.jmrit.logix.Portal; 028import jmri.jmrit.picker.PickListModel; 029import jmri.util.swing.JmriJOptionPane; 030 031/** 032 * @author Pete Cressman Copyright: Copyright (c) 2011 033 */ 034public class EditCircuitFrame extends EditFrame implements PropertyChangeListener { 035 036 private JTextField _systemName; 037 private JTextField _blockName; 038 private JTextField _detectorSensorName; 039 private JTextField _errorSensorName; 040 private JTextField _blockState; 041 private JTextField _numTrackSeg; 042 private JTextField _numTurnouts; 043 private LengthPanel _lengthPanel; 044 private JPanel _namePanel; 045 private boolean _create; 046 047 // Sensor list 048 OpenPickListButton<Sensor> _pickTable; 049 050 public EditCircuitFrame(String title, CircuitBuilder parent, OBlock block) { 051 super(title, parent, block); 052 _create = (block == null); 053 updateContentPanel(_create); 054 _homeBlock.addPropertyChangeListener("deleted", this); 055 pack(); 056 } 057 058 @Override 059 protected JPanel makeContentPanel() { 060 JPanel contentPane = new JPanel(); 061 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 062 _blockName = new JTextField(); 063 _detectorSensorName = new JTextField(); 064 _errorSensorName = new JTextField(); 065 _blockState = new JTextField(); 066 _numTrackSeg = new JTextField(); 067 _numTurnouts = new JTextField(); 068 JPanel p = new JPanel(); 069 070 p.add(new JLabel(Bundle.getMessage("AddRemoveIcons"))); 071 contentPane.add(p); 072 contentPane.add(Box.createVerticalStrut(STRUT_SIZE)); 073 074 JPanel panel = new JPanel(); 075 // panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 076 panel.add(CircuitBuilder.makeTextBoxPanel(false, _blockState, "blockState", false, null)); 077 _blockState.setPreferredSize(new Dimension(150, _blockState.getPreferredSize().height)); 078 contentPane.add(panel); 079 080 _namePanel = new JPanel(); 081 _namePanel.setLayout(new BoxLayout(_namePanel, BoxLayout.Y_AXIS)); 082 contentPane.add(_namePanel); 083 084 panel = new JPanel(); 085 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 086 JPanel _buttonPanel = new JPanel(); 087 _buttonPanel.setLayout(new FlowLayout()); 088 panel.add(_buttonPanel); 089 contentPane.add(panel); 090 091 contentPane.add(Box.createVerticalStrut(STRUT_SIZE)); 092 p = new JPanel(); 093 p.add(new JLabel(Bundle.getMessage("numTrackElements"))); 094 contentPane.add(p); 095 096 panel = new JPanel(); 097 // panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 098 panel.add(Box.createHorizontalGlue()); 099 panel.add(CircuitBuilder.makeTextBoxPanel( 100 false, _numTrackSeg, "Segments", false, null)); 101 _numTrackSeg.setPreferredSize(new Dimension(20, _numTrackSeg.getPreferredSize().height)); 102 panel.add(Box.createHorizontalStrut(STRUT_SIZE)); 103 104 panel.add(CircuitBuilder.makeTextBoxPanel( 105 false, _numTurnouts, "Turnouts", false, null)); 106 _numTurnouts.setPreferredSize(new Dimension(20, _numTurnouts.getPreferredSize().height)); 107 panel.add(Box.createHorizontalStrut(STRUT_SIZE)); 108 contentPane.add(panel); 109 contentPane.add(Box.createVerticalStrut(STRUT_SIZE)); 110 111 panel = new JPanel(); 112 // panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 113 _detectorSensorName.setPreferredSize(new Dimension(300, _detectorSensorName.getPreferredSize().height)); 114 panel.add(CircuitBuilder.makeTextBoxPanel( 115 false, _detectorSensorName, "DetectionSensor", true, "detectorSensorName")); 116 _detectorSensorName.setToolTipText(Bundle.getMessage("detectorSensorName")); 117 contentPane.add(panel); 118 119 panel = new JPanel(); 120 // panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 121 _errorSensorName.setPreferredSize(new Dimension(300, _errorSensorName.getPreferredSize().height)); 122 panel.add(CircuitBuilder.makeTextBoxPanel( 123 false, _errorSensorName, "ErrorSensor", true, "detectorErrorName")); 124 _errorSensorName.setToolTipText(Bundle.getMessage("detectorErrorName")); 125 contentPane.add(panel); 126 127 String[] blurbLines = { Bundle.getMessage("DragOccupancySensor", Bundle.getMessage("DetectionSensor")), 128 Bundle.getMessage("DragErrorName", Bundle.getMessage("ErrorSensor"))}; 129 _pickTable = new OpenPickListButton<>(blurbLines, PickListModel.sensorPickModelInstance(), 130 this, Bundle.getMessage("OpenPicklist", Bundle.getMessage("BeanNameSensor"))); 131 contentPane.add(_pickTable.getButtonPanel()); 132 contentPane.add(Box.createVerticalStrut(STRUT_SIZE)); 133 134 _lengthPanel = new LengthPanel(_homeBlock, LengthPanel.BLOCK_LENGTH, "TooltipPathLength"); 135 _lengthPanel.changeUnits(); 136 _lengthPanel.setLength(_homeBlock.getLengthMm()); 137 contentPane.add(_lengthPanel); 138 contentPane.add(Box.createVerticalStrut(STRUT_SIZE)); 139 140 contentPane.add(makeDoneButtonPanel()); 141 return contentPane; 142 } 143 private JPanel makeCreateBlockPanel() { 144 _systemName = new JTextField(); 145 _systemName.setText(_homeBlock.getSystemName()); 146 _blockName.setText(_homeBlock.getUserName()); 147 JPanel panel = new JPanel(); 148 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 149 panel.add(CircuitBuilder.makeTextBoxPanel( 150 false, _systemName, "ColumnSystemName", true, "TooltipBlockName")); 151 _systemName.setPreferredSize(new Dimension(300, _systemName.getPreferredSize().height)); 152 panel.add(CircuitBuilder.makeTextBoxPanel( 153 false, _blockName, "blockName", true, "TooltipBlockName")); 154 _blockName.setPreferredSize(new Dimension(300, _blockName.getPreferredSize().height)); 155 156 JPanel buttonPanel = new JPanel(); 157 buttonPanel.setLayout(new FlowLayout()); 158 JButton createButton = new JButton(Bundle.getMessage("buttonCreate")); 159 createButton.addActionListener((ActionEvent a) -> createBlock()); 160 createButton.setToolTipText(Bundle.getMessage("createOBlock")); 161 buttonPanel.add(createButton); 162 163 panel.add(buttonPanel); 164 panel.add(Box.createVerticalStrut(STRUT_SIZE)); 165 return panel; 166 } 167 168 private JPanel makeEditBlockPanel() { 169 _blockName.setText(_homeBlock.getUserName()); 170 JPanel panel = new JPanel(); 171 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 172 panel.add(CircuitBuilder.makeTextBoxPanel( 173 false, _blockName, "blockName", true, "TooltipBlockName")); 174 _blockName.setPreferredSize(new Dimension(300, _blockName.getPreferredSize().height)); 175 176 JPanel buttonPanel = new JPanel(); 177 buttonPanel.setLayout(new FlowLayout()); 178 179 JButton changeButton = new JButton(Bundle.getMessage("buttonChangeName")); 180 changeButton.addActionListener((ActionEvent a) -> changeBlockName()); 181 changeButton.setToolTipText(Bundle.getMessage("ToolTipChangeName")); 182 buttonPanel.add(changeButton); 183 184 JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 185 deleteButton.addActionListener((ActionEvent a) -> deleteCircuit()); 186 deleteButton.setToolTipText(Bundle.getMessage("ToolTipDeleteCircuit")); 187 buttonPanel.add(deleteButton); 188 189 panel.add(buttonPanel); 190 panel.add(Box.createVerticalStrut(STRUT_SIZE)); 191 return panel; 192 } 193 194 @Override 195 protected JPanel makeDoneButtonPanel() { 196 JPanel buttonPanel = new JPanel(); 197 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); 198 JPanel panel = new JPanel(); 199 panel.setLayout(new FlowLayout()); 200 201 JButton convertButton = new JButton(Bundle.getMessage("ButtonConvertIcon")); 202 convertButton.addActionListener((ActionEvent a) -> convertIcons()); 203 convertButton.setToolTipText(Bundle.getMessage("ToolTipConvertIcon")); 204 panel.add(convertButton); 205 206 JButton doneButton = new JButton(Bundle.getMessage("ButtonDone")); 207 doneButton.addActionListener((ActionEvent a) -> { 208 if (_create) { 209 closeCreate(); 210 } else { 211 closingEvent(false); 212 } 213 }); 214 panel.add(doneButton); 215 buttonPanel.add(panel); 216 217 return buttonPanel; 218 } 219 220 private void convertIcons() { 221 _parent.setIconGroup(_homeBlock); 222 _parent.queryConvertTrackIcons(_homeBlock, "PortalOrPath"); 223 this.toFront(); 224 } 225 226 /* 227 * *********************** end setup ************************* 228 */ 229 230 private void createBlock() { 231 String userName = _blockName.getText().trim(); 232 String systemName = _systemName.getText().trim(); 233 OBlockManager mgr = InstanceManager.getDefault(OBlockManager.class); 234 StringBuilder sb = new StringBuilder (); 235 if (userName.length() > 0) { 236 OBlock block = mgr.getByUserName(userName); 237 if (block != null) { 238 sb.append(Bundle.getMessage("duplicateName", userName, block.getSystemName())); 239 sb.append("\n"); 240 } 241 } 242 if (!mgr.isValidSystemNameFormat(systemName)) { 243 sb.append(Bundle.getMessage("sysnameOBlock")); 244 sb.append("\n"); 245 } else { 246 OBlock block = mgr.getBySystemName(systemName); 247 if (block != null) { 248 sb.append(Bundle.getMessage("duplicateName", systemName, block.getUserName())); 249 sb.append("\n"); 250 } 251 } 252 if (sb.toString().length() > 0) { 253 JmriJOptionPane.showMessageDialog(this, sb.toString(), 254 Bundle.getMessage("editCiruit"), JmriJOptionPane.INFORMATION_MESSAGE); 255 _systemName.setText(_homeBlock.getSystemName()); 256 return; 257 } 258 _homeBlock = mgr.createNewOBlock(systemName, userName); 259 updateContentPanel(false); 260 } 261 262 private void changeBlockName() { 263 String name = _blockName.getText().trim(); 264 String msg = null; 265 if (name.length() == 0) { 266 msg = Bundle.getMessage("TooltipBlockName"); 267 } else { 268 OBlock block = InstanceManager.getDefault(OBlockManager.class).getByUserName(name); 269 if (block != null) { 270 msg = Bundle.getMessage("duplicateName", name, block.getDisplayName(DisplayOptions.QUOTED_USERNAME_SYSTEMNAME)); 271 } 272 } 273 if (msg != null) { 274 JmriJOptionPane.showMessageDialog(this, msg, 275 Bundle.getMessage("editCiruit"), JmriJOptionPane.INFORMATION_MESSAGE); 276 return; 277 278 } 279 _homeBlock.setUserName(name); 280 // block user name change will change portal names. Change PortalIcon names to match 281 for (Positionable p : _parent.getCircuitIcons(_homeBlock)) { 282 if (p instanceof PortalIcon) { 283 PortalIcon icon = (PortalIcon)p; 284 Portal portal = icon.getPortal(); 285 icon.setName(portal.getName()); 286 icon.setToolTip(new ToolTip(portal.getDescription(), 0, 0, icon)); 287 } 288 } 289 } 290 291 private void deleteCircuit() { 292 int result = JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("confirmBlockDelete"), 293 Bundle.getMessage("editCiruit"), JmriJOptionPane.YES_NO_OPTION, 294 JmriJOptionPane.QUESTION_MESSAGE); 295 if (result == JmriJOptionPane.YES_OPTION) { 296 _parent.removeBlock(_homeBlock); 297 closingEvent(true, null); // No Messages, just close 298 } 299 } 300 301 private void updateContentPanel(boolean create) { 302 updateIconList(_parent._editor.getSelectionGroup()); 303 String name = ""; 304 Sensor sensor = _homeBlock.getSensor(); 305 if (sensor != null) { 306 name = sensor.getDisplayName(); 307 _detectorSensorName.setText(name); 308 } 309 310 sensor = _homeBlock.getErrorSensor(); 311 if (sensor != null) { 312 name = sensor.getDisplayName(); 313 _errorSensorName.setText(name); 314 } 315 316 int state = _homeBlock.getState(); 317 StringBuilder stateText = new StringBuilder(); 318 if ((state & OBlock.UNKNOWN) != 0) { 319 stateText.append("Unknown "); 320 } 321 if ((state & OBlock.OCCUPIED) != 0) { 322 stateText.append("Occupied "); 323 } 324 if ((state & OBlock.UNOCCUPIED) != 0) { 325 stateText.append("Unoccupied "); 326 } 327 if ((state & OBlock.INCONSISTENT) != 0) { 328 stateText.append("Inconsistent "); 329 } 330 if ((state & OBlock.ALLOCATED) != 0) { 331 stateText.append("Allocated "); 332 } 333 if ((state & OBlock.RUNNING) != 0) { 334 stateText.append("Positioned "); 335 } 336 if ((state & OBlock.OUT_OF_SERVICE) != 0) { 337 stateText.append("OutOf Service "); 338 } 339 if ((state & OBlock.UNDETECTED) != 0) { 340 stateText.append("Dark "); 341 } 342 if ((state & OBlock.TRACK_ERROR) != 0) { 343 stateText.append("TrackError "); 344 } 345 if (state == 0) { 346 stateText.append("Not Initialized"); 347 } 348 if (log.isDebugEnabled()) { 349 log.debug("updateContentPanel: state= {}", stateText); 350 } 351 _blockState.setText(stateText.toString()); 352 353 JPanel panel; 354 if (create) { 355 panel = makeCreateBlockPanel(); 356 } else { 357 panel = makeEditBlockPanel(); 358 _create = false; 359 } 360 _namePanel.removeAll(); 361 _namePanel.add(panel); 362 _namePanel.invalidate(); 363 pack(); 364 } 365 366 private void closeCreate() { 367 StringBuilder sb = new StringBuilder (); 368 String sysName = _homeBlock.getSystemName(); 369 OBlock block = InstanceManager.getDefault(OBlockManager.class).getBySystemName(sysName); 370 if (block == null) { 371 // get rid of icon selections 372 for (Positionable pos : _parent.getCircuitIcons(_homeBlock)) { 373 if (pos instanceof IndicatorTrack) { 374 ((IndicatorTrack) pos).setOccBlockHandle(null); 375 } 376 } 377 _parent._editor.getSelectionGroup().clear(); 378 sb.append( Bundle.getMessage("notCreated", _systemName.getText().trim())); 379 closingEvent(false, sb.toString()); 380 if (_pickTable != null) { 381 _pickTable.closePickList(); 382 } 383 } else { 384 closingEvent(false); 385 } 386 } 387 388 @Override 389 protected void closingEvent(boolean close) { 390 StringBuffer sb = new StringBuffer(); 391 String msg = checkForSensors(); 392 if (msg != null) { 393 sb.append(msg); 394 sb.append("\n"); 395 } 396 String name = _blockName.getText().trim(); 397 if (name.length() == 0) { 398 msg = Bundle.getMessage("blankUserName"); 399 if (msg != null) { 400 sb.append(msg); 401 sb.append("\n"); 402 } 403 } else if (!name.equals(_homeBlock.getUserName())) { 404 msg = Bundle.getMessage("changeBlockName", name, _homeBlock.getDisplayName(DisplayOptions.QUOTED_USERNAME_SYSTEMNAME)); 405 if (msg != null) { 406 sb.append(msg); 407 sb.append("\n"); 408 } 409 } 410 _parent.setIconGroup(_homeBlock); 411 msg = _parent.checkForTrackIcons(_homeBlock, "PortalOrPath"); 412 if (msg.length() > 0) { 413 sb.append(msg); 414 sb.append("\n"); 415 } 416 if (_lengthPanel.getLength() <= 0.001) { 417 msg = Bundle.getMessage("noBlockLength"); 418 if (msg != null) { 419 sb.append(msg); 420 sb.append("\n"); 421 } 422 } else { 423 _homeBlock.setLength(_lengthPanel.getLength()); 424 } 425 426 closingEvent(close, sb.toString()); 427 if (_pickTable != null) { 428 _pickTable.closePickList(); 429 } 430 } 431 432 private String checkForSensors() { 433 String name = _detectorSensorName.getText(); 434 String errName = _errorSensorName.getText(); 435 if (!_homeBlock.setSensor(name)) { 436 return java.text.MessageFormat.format(Bundle.getMessage("badSensorName"), name); 437 } 438 if (errName.length() > 2) { 439 if (_homeBlock.getSensor() == null) { 440 int result = JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("mixedSensors"), 441 Bundle.getMessage("noSensor"), JmriJOptionPane.YES_NO_OPTION, 442 JmriJOptionPane.QUESTION_MESSAGE); 443 if (result == JmriJOptionPane.YES_OPTION) { 444 if (!_homeBlock.setSensor(errName)) { 445 return java.text.MessageFormat.format(Bundle.getMessage("badSensorName"), errName); 446 } else { 447 _homeBlock.setErrorSensor(null); 448 _detectorSensorName.setText(_homeBlock.getSensor().getDisplayName()); 449 _errorSensorName.setText(null); 450 } 451 } else { 452 if (!_homeBlock.setErrorSensor(errName)) { 453 return java.text.MessageFormat.format(Bundle.getMessage("badSensorName"), errName); 454 } 455 } 456 } else { 457 if (!_homeBlock.setErrorSensor(errName)) { 458 return java.text.MessageFormat.format(Bundle.getMessage("badSensorName"), errName); 459 } 460 } 461 } else if (errName.trim().length() == 0){ { 462 _homeBlock.setErrorSensor(null); 463 } 464 465 } 466 Sensor sensor = _homeBlock.getSensor(); 467 if (sensor == null) { 468 return Bundle.getMessage("noDetecterSensor"); 469 } else if (sensor.equals(_homeBlock.getErrorSensor())) { 470 _homeBlock.setErrorSensor(null); 471 _errorSensorName.setText(null); 472 return java.text.MessageFormat.format(Bundle.getMessage("DuplSensorRemoved"), 473 sensor.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)); 474 } 475 return null; 476 } 477 478 protected void updateIconList(java.util.List<Positionable> icons) { 479 //if (log.isDebugEnabled()) log.debug( 480 int segments = 0; 481 int turnouts = 0; 482 if (icons != null) { 483 if (log.isDebugEnabled()) { 484 log.debug("updateIconList: icons.size()= {}", icons.size()); 485 } 486 for (Positionable pos : icons) { 487 if (pos instanceof IndicatorTurnoutIcon) { 488 turnouts++; 489 } else if (pos instanceof IndicatorTrackIcon) { 490 segments++; 491 } else if (pos instanceof TurnoutIcon) { 492 turnouts++; 493 } else { 494 segments++; 495 } 496 } 497 } 498 _numTrackSeg.setText(String.valueOf(segments)); 499 _numTurnouts.setText(String.valueOf(turnouts)); 500 } 501 502 @Override 503 public void propertyChange(PropertyChangeEvent e) { 504 if (e.getPropertyName().equals("deleted")) { 505 closingEvent(true, null); // No Messages, just close 506 } 507 } 508 509 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EditCircuitFrame.class); 510 511}