001package jmri.jmrit.operations.locations.gui; 002 003import java.awt.*; 004import java.awt.event.ActionEvent; 005import java.awt.event.MouseEvent; 006import java.util.ArrayList; 007import java.util.List; 008 009import javax.swing.*; 010 011import jmri.*; 012import jmri.jmrit.operations.*; 013import jmri.jmrit.operations.locations.*; 014import jmri.jmrit.operations.locations.divisions.*; 015import jmri.jmrit.operations.locations.schedules.tools.SchedulesAndStagingAction; 016import jmri.jmrit.operations.locations.tools.*; 017import jmri.jmrit.operations.rollingstock.cars.CarTypes; 018import jmri.jmrit.operations.rollingstock.engines.EngineTypes; 019import jmri.jmrit.operations.routes.Route; 020import jmri.jmrit.operations.routes.RouteManager; 021import jmri.jmrit.operations.routes.tools.ShowRoutesServingLocationAction; 022import jmri.jmrit.operations.routes.tools.ShowRoutesServingLocationFrame; 023import jmri.jmrit.operations.setup.Control; 024import jmri.jmrit.operations.setup.Setup; 025import jmri.jmrit.operations.trains.TrainCommon; 026import jmri.swing.NamedBeanComboBox; 027import jmri.util.swing.JmriJOptionPane; 028 029/** 030 * Frame for user edit of location 031 * 032 * @author Dan Boudreau Copyright (C) 2008, 2010, 2011, 2012, 2013 033 */ 034public class LocationEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 035 036 YardTableModel yardModel = new YardTableModel(); 037 JTable yardTable = new JTable(yardModel); 038 JScrollPane yardPane = new JScrollPane(yardTable); 039 040 SpurTableModel spurModel = new SpurTableModel(); 041 JTable spurTable = new JTable(spurModel) { 042 // create tool tip for Hold column 043 @Override 044 public String getToolTipText(MouseEvent e) { 045 int colIndex = columnAtPoint(e.getPoint()); 046 int realColumnIndex = convertColumnIndexToModel(colIndex); 047 if (realColumnIndex == TrackTableModel.HOLD_COLUMN) { 048 return Bundle.getMessage("HoldCarsWithCustomLoads"); 049 } 050 return null; 051 } 052 }; 053 JScrollPane spurPane = new JScrollPane(spurTable); 054 055 InterchangeTableModel interchangeModel = new InterchangeTableModel(); 056 JTable interchangeTable = new JTable(interchangeModel) { 057 // create tool tip for Routed column 058 @Override 059 public String getToolTipText(MouseEvent e) { 060 int colIndex = columnAtPoint(e.getPoint()); 061 int realColumnIndex = convertColumnIndexToModel(colIndex); 062 if (realColumnIndex == TrackTableModel.ROUTED_COLUMN) { 063 return Bundle.getMessage("TipOnlyCarsWithFD"); 064 } 065 return null; 066 } 067 }; 068 JScrollPane interchangePane = new JScrollPane(interchangeTable); 069 070 StagingTableModel stagingModel = new StagingTableModel(); 071 JTable stagingTable = new JTable(stagingModel) { 072 // create tool tip for Routed column 073 @Override 074 public String getToolTipText(MouseEvent e) { 075 int colIndex = columnAtPoint(e.getPoint()); 076 int realColumnIndex = convertColumnIndexToModel(colIndex); 077 if (realColumnIndex == TrackTableModel.ROUTED_COLUMN) { 078 return Bundle.getMessage("TipOnlyCarsWithFD"); 079 } 080 return null; 081 } 082 }; 083 JScrollPane stagingPane = new JScrollPane(stagingTable); 084 085 LocationManager locationManager = InstanceManager.getDefault(LocationManager.class); 086 public Location _location = null; 087 088 ArrayList<JCheckBox> checkBoxes = new ArrayList<>(); 089 JPanel panelCheckBoxes = new JPanel(); 090 JScrollPane typePane = new JScrollPane(panelCheckBoxes); 091 092 JPanel directionPanel = new JPanel(); 093 094 // major buttons 095 JButton clearButton = new JButton(Bundle.getMessage("ClearAll")); 096 JButton setButton = new JButton(Bundle.getMessage("SelectAll")); 097 JButton autoSelectButton = new JButton(Bundle.getMessage("AutoSelect")); 098 JButton editDivisionButton = new JButton(Bundle.getMessage("ButtonEdit")); 099 JButton saveLocationButton = new JButton(Bundle.getMessage("SaveLocation")); 100 JButton deleteLocationButton = new JButton(Bundle.getMessage("DeleteLocation")); 101 JButton addLocationButton = new JButton(Bundle.getMessage("AddLocation")); 102 JButton addYardButton = new JButton(Bundle.getMessage("AddYard")); 103 JButton addSpurButton = new JButton(Bundle.getMessage("AddSpur")); 104 JButton addInterchangeButton = new JButton(Bundle.getMessage("AddInterchange")); 105 JButton addStagingButton = new JButton(Bundle.getMessage("AddStaging")); 106 107 // check boxes 108 JCheckBox northCheckBox = new JCheckBox(Bundle.getMessage("North")); 109 JCheckBox southCheckBox = new JCheckBox(Bundle.getMessage("South")); 110 JCheckBox eastCheckBox = new JCheckBox(Bundle.getMessage("East")); 111 JCheckBox westCheckBox = new JCheckBox(Bundle.getMessage("West")); 112 113 // radio buttons 114 JRadioButton stagingRadioButton = new JRadioButton(Bundle.getMessage("StagingOnly")); 115 JRadioButton interchangeRadioButton = new JRadioButton(Bundle.getMessage("Interchange")); 116 JRadioButton yardRadioButton = new JRadioButton(Bundle.getMessage("Yards")); 117 JRadioButton spurRadioButton = new JRadioButton(Bundle.getMessage("Spurs")); 118 119 // text field 120 JTextField locationNameTextField = new JTextField(Control.max_len_string_location_name); 121 122 // text area 123 JTextArea commentTextArea = new JTextArea(2, 60); 124 JScrollPane commentScroller = new JScrollPane(commentTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 125 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 126 JColorChooser commentColorChooser = new JColorChooser(); 127 128 // combo boxes 129 protected JComboBox<Division> divisionComboBox = InstanceManager.getDefault(DivisionManager.class).getComboBox(); 130 131 // Reader selection dropdown. 132 NamedBeanComboBox<Reporter> readerSelector; 133 134 JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools")); 135 136 public static final String NAME = Bundle.getMessage("Name"); 137 public static final int MAX_NAME_LENGTH = Control.max_len_string_location_name; 138 public static final String DISPOSE = "dispose"; // NOI18N 139 140 public LocationEditFrame(Location location) { 141 super(Bundle.getMessage("TitleLocationEdit")); 142 143 _location = location; 144 145 // Set up the jtable in a Scroll Pane.. 146 typePane = new JScrollPane(panelCheckBoxes); 147 typePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 148 typePane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TypesLocation"))); 149 150 yardPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 151 yardPane.setBorder(BorderFactory.createTitledBorder("")); 152 153 spurPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 154 spurPane.setBorder(BorderFactory.createTitledBorder("")); 155 156 interchangePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 157 interchangePane.setBorder(BorderFactory.createTitledBorder("")); 158 159 stagingPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 160 stagingPane.setBorder(BorderFactory.createTitledBorder("")); 161 162 // button group 163 ButtonGroup opsGroup = new ButtonGroup(); 164 opsGroup.add(spurRadioButton); 165 opsGroup.add(yardRadioButton); 166 opsGroup.add(interchangeRadioButton); 167 opsGroup.add(stagingRadioButton); 168 169 if (_location != null) { 170 enableButtons(true); 171 locationNameTextField.setText(_location.getName()); 172 commentTextArea.setText(_location.getComment()); 173 divisionComboBox.setSelectedItem(_location.getDivision()); 174 yardModel.initTable(yardTable, location); 175 spurModel.initTable(spurTable, location); 176 interchangeModel.initTable(interchangeTable, location); 177 stagingModel.initTable(stagingTable, location); 178 _location.addPropertyChangeListener(this); 179 if (!_location.isStaging()) { 180 if (spurModel.getRowCount() > 0) { 181 spurRadioButton.setSelected(true); 182 } else if (yardModel.getRowCount() > 0) { 183 yardRadioButton.setSelected(true); 184 } else if (interchangeModel.getRowCount() > 0) { 185 interchangeRadioButton.setSelected(true); 186 } else { 187 spurRadioButton.setSelected(true); 188 } 189 } else { 190 stagingRadioButton.setSelected(true); 191 } 192 setTrainDirectionBoxes(); 193 } else { 194 enableButtons(false); 195 spurRadioButton.setSelected(true); 196 } 197 198 setVisibleTrackType(); 199 200 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 201 202 // Layout the panel by rows 203 // row 1 204 JPanel p1 = new JPanel(); 205 p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 206 JScrollPane p1Pane = new JScrollPane(p1); 207 p1Pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); 208 p1Pane.setMinimumSize(new Dimension(300, 3 * locationNameTextField.getPreferredSize().height)); 209 p1Pane.setBorder(BorderFactory.createTitledBorder("")); 210 211 // row 1a 212 JPanel pName = new JPanel(); 213 pName.setLayout(new GridBagLayout()); 214 pName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Name"))); 215 216 addItem(pName, locationNameTextField, 0, 0); 217 218 // row 1b 219 directionPanel.setLayout(new GridBagLayout()); 220 directionPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainLocation"))); 221 addItem(directionPanel, northCheckBox, 1, 0); 222 addItem(directionPanel, southCheckBox, 2, 0); 223 addItem(directionPanel, eastCheckBox, 3, 0); 224 addItem(directionPanel, westCheckBox, 4, 0); 225 226 p1.add(pName); 227 p1.add(directionPanel); 228 229 // division field 230 JPanel pDivision = new JPanel(); 231 pDivision.setLayout(new GridBagLayout()); 232 pDivision.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Division"))); 233 addItem(pDivision, divisionComboBox, 2, 0); 234 addItem(pDivision, editDivisionButton, 3, 0); 235 setDivisionButtonText(); 236 237 // row 5 238 panelCheckBoxes.setLayout(new GridBagLayout()); 239 updateCheckboxes(); 240 241 // row 9 242 JPanel pOp = new JPanel(); 243 pOp.setLayout(new GridBagLayout()); 244 pOp.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TracksAtLocation"))); 245 pOp.add(spurRadioButton); 246 pOp.add(yardRadioButton); 247 pOp.add(interchangeRadioButton); 248 pOp.add(stagingRadioButton); 249 250 // row 11 251 JPanel pC = new JPanel(); 252 pC.setLayout(new GridBagLayout()); 253 pC.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Comment"))); 254 addItem(pC, commentScroller, 0, 0); 255 if (_location != null) { 256 addItem(pC, OperationsPanel.getColorChooserPanel(_location.getCommentWithColor(), commentColorChooser), 2, 0); 257 } else { 258 addItem(pC, OperationsPanel.getColorChooserPanel("", commentColorChooser), 2, 0); 259 } 260 261 // adjust text area width based on window size less color chooser 262 Dimension d = new Dimension(getPreferredSize().width - 100, getPreferredSize().height); 263 adjustTextAreaColumnWidth(commentScroller, commentTextArea, d); 264 265 JPanel readerPanel = new JPanel(); 266 readerPanel.setVisible(false); 267 // reader row 268 if (Setup.isRfidEnabled()) { 269 ReporterManager reporterManager = InstanceManager.getDefault(ReporterManager.class); 270 readerSelector = new NamedBeanComboBox<Reporter>(reporterManager); 271 readerSelector.setAllowNull(true); 272 readerPanel.setLayout(new GridBagLayout()); 273 readerPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("idReporter"))); 274 addItem(readerPanel, readerSelector, 0, 0); 275 readerPanel.setVisible(true); 276 if (_location != null) { 277 readerSelector.setSelectedItem(_location.getReporter()); 278 } 279 } 280 281 // row 12 282 JPanel pB = new JPanel(); 283 pB.setLayout(new GridBagLayout()); 284 addItem(pB, deleteLocationButton, 0, 0); 285 addItem(pB, addLocationButton, 1, 0); 286 addItem(pB, saveLocationButton, 3, 0); 287 288 getContentPane().add(p1Pane); 289 getContentPane().add(pDivision); 290 getContentPane().add(typePane); 291 getContentPane().add(pOp); 292 getContentPane().add(yardPane); 293 getContentPane().add(addYardButton); 294 getContentPane().add(spurPane); 295 getContentPane().add(addSpurButton); 296 getContentPane().add(interchangePane); 297 getContentPane().add(addInterchangeButton); 298 getContentPane().add(stagingPane); 299 getContentPane().add(addStagingButton); 300 getContentPane().add(pC); 301 getContentPane().add(readerPanel); 302 getContentPane().add(pB); 303 304 // setup buttons 305 addButtonAction(setButton); 306 addButtonAction(clearButton); 307 addButtonAction(autoSelectButton); 308 addButtonAction(editDivisionButton); 309 addButtonAction(deleteLocationButton); 310 addButtonAction(addLocationButton); 311 addButtonAction(saveLocationButton); 312 addButtonAction(addYardButton); 313 addButtonAction(addSpurButton); 314 addButtonAction(addInterchangeButton); 315 addButtonAction(addStagingButton); 316 317 // add tool tips 318 autoSelectButton.setToolTipText(Bundle.getMessage("TipAutoSelect")); 319 320 addRadioButtonAction(spurRadioButton); 321 addRadioButtonAction(yardRadioButton); 322 addRadioButtonAction(interchangeRadioButton); 323 addRadioButtonAction(stagingRadioButton); 324 325 addCheckBoxTrainAction(northCheckBox); 326 addCheckBoxTrainAction(southCheckBox); 327 addCheckBoxTrainAction(eastCheckBox); 328 addCheckBoxTrainAction(westCheckBox); 329 330 addComboBoxAction(divisionComboBox); 331 332 // add property listeners 333 InstanceManager.getDefault(CarTypes.class).addPropertyChangeListener(this); 334 InstanceManager.getDefault(EngineTypes.class).addPropertyChangeListener(this); 335 InstanceManager.getDefault(DivisionManager.class).addPropertyChangeListener(this); 336 InstanceManager.getDefault(Setup.class).addPropertyChangeListener(this); 337 338 // build menu 339 JMenuBar menuBar = new JMenuBar(); 340 341 loadToolMenu(); 342 menuBar.add(toolMenu); 343 setJMenuBar(menuBar); 344 addHelpMenu("package.jmri.jmrit.operations.Operations_AddLocation", true); // NOI18N 345 346 initMinimumSize(new Dimension(Control.panelWidth600, Control.panelHeight500)); 347 } 348 349 private void loadToolMenu() { 350 toolMenu.removeAll(); 351 toolMenu.add(new LocationCopyAction(_location)); 352 toolMenu.add(new TrackCopyAction(null, _location)); 353 toolMenu.add(new ChangeTracksTypeAction(this)); 354 if (_location != null && !_location.isStaging()) { 355 toolMenu.add(new LocationTrackBlockingOrderAction(_location)); 356 } 357 toolMenu.add(new ShowTrackMovesAction()); 358 toolMenu.add(new EditCarTypeAction()); 359 if (Setup.isVsdPhysicalLocationEnabled()) { 360 toolMenu.add(new SetPhysicalLocationAction(_location)); 361 } 362 toolMenu.addSeparator(); 363 toolMenu.add(new ModifyLocationsAction(_location)); 364 toolMenu.add(new ModifyLocationsCarLoadsAction(_location)); 365 toolMenu.addSeparator(); 366 toolMenu.add(new ShowCarsByLocationAction(false, _location, null)); 367 toolMenu.add(new ShowTrainsServingLocationAction(_location, null)); 368 toolMenu.add(new ShowRoutesServingLocationAction(_location)); 369 if (_location != null && _location.isStaging()) { 370 toolMenu.add(new SchedulesAndStagingAction()); 371 } 372 toolMenu.addSeparator(); 373 toolMenu.add(new PrintLocationsAction(false, _location)); 374 toolMenu.add(new PrintLocationsAction(true, _location)); 375 } 376 377 // frames 378 DivisionEditFrame def = null; 379 YardEditFrame yef = null; 380 SpurEditFrame sef = null; 381 InterchangeEditFrame ief = null; 382 StagingEditFrame stef = null; 383 384 // Save, Delete, Add 385 @Override 386 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 387 if (ae.getSource() == editDivisionButton) { 388 if (def != null) { 389 def.dispose(); 390 } 391 def = new DivisionEditFrame((Division) divisionComboBox.getSelectedItem()); 392 } 393 if (ae.getSource() == addYardButton) { 394 yef = new YardEditFrame(); 395 yef.initComponents(_location, null); 396 } 397 if (ae.getSource() == addSpurButton) { 398 sef = new SpurEditFrame(); 399 sef.initComponents(_location, null); 400 } 401 if (ae.getSource() == addInterchangeButton) { 402 ief = new InterchangeEditFrame(); 403 ief.initComponents(_location, null); 404 } 405 if (ae.getSource() == addStagingButton) { 406 stef = new StagingEditFrame(); 407 stef.initComponents(_location, null); 408 } 409 410 if (ae.getSource() == saveLocationButton) { 411 log.debug("location save button activated"); 412 Location l = locationManager.getLocationByName(locationNameTextField.getText()); 413 if (_location == null && l == null) { 414 saveNewLocation(); 415 } else { 416 if (l != null && l != _location) { 417 reportLocationExists(Bundle.getMessage("save")); 418 return; 419 } 420 saveLocation(); 421 if (Setup.isCloseWindowOnSaveEnabled()) { 422 dispose(); 423 } 424 } 425 } 426 if (ae.getSource() == deleteLocationButton) { 427 log.debug("location delete button activated"); 428 deleteLocation(); 429 // save location file 430 OperationsXml.save(); 431 } 432 if (ae.getSource() == addLocationButton) { 433 Location l = locationManager.getLocationByName(locationNameTextField.getText()); 434 if (l != null) { 435 reportLocationExists(Bundle.getMessage("add")); 436 return; 437 } 438 saveNewLocation(); 439 } 440 if (ae.getSource() == setButton) { 441 selectCheckboxes(true); 442 } 443 if (ae.getSource() == clearButton) { 444 selectCheckboxes(false); 445 } 446 if (ae.getSource() == autoSelectButton) { 447 log.debug("auto select button pressed"); 448 if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("autoSelectCarTypes?"), 449 Bundle.getMessage("autoSelectLocations?"), JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 450 return; 451 } 452 autoSelectCheckboxes(); 453 } 454 } 455 456 private void saveNewLocation() { 457 if (!checkName(Bundle.getMessage("add"))) { 458 return; 459 } 460 Location location = locationManager.newLocation(locationNameTextField.getText()); 461 yardModel.initTable(yardTable, location); 462 spurModel.initTable(spurTable, location); 463 interchangeModel.initTable(interchangeTable, location); 464 stagingModel.initTable(stagingTable, location); 465 _location = location; 466 _location.addPropertyChangeListener(this); 467 468 updateCheckboxes(); 469 enableButtons(true); 470 setTrainDirectionBoxes(); 471 saveLocation(); 472 loadToolMenu(); 473 } 474 475 private void deleteLocation() { 476 Location location = locationManager.getLocationByName(locationNameTextField.getText()); 477 if (location == null) { 478 return; 479 } 480 // check to see if any route uses this location 481 Route route = InstanceManager.getDefault(RouteManager.class).isLocationInUse(location); 482 if (route != null) { 483 JmriJOptionPane.showMessageDialog(this, 484 Bundle.getMessage("RouteUsesLocation", route.getName(), location.getName()), 485 Bundle.getMessage("CanNotDeleteLocation"), JmriJOptionPane.ERROR_MESSAGE); 486 // show all the routes using this location 487 ShowRoutesServingLocationFrame frame = new ShowRoutesServingLocationFrame(); 488 frame.initComponents(location); 489 return; 490 } 491 int count = location.getNumberRS(); 492 if (count > 0) { 493 if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("ThereAreCars", Integer.toString(count)), 494 Bundle.getMessage("deletelocation?"), 495 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 496 return; 497 } 498 } else { 499 if (JmriJOptionPane.showConfirmDialog(this, 500 Bundle.getMessage("DoYouWantToDeleteLocation", locationNameTextField.getText()), 501 Bundle.getMessage("deletelocation?"), 502 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 503 return; 504 } 505 } 506 507 yardModel.dispose(); 508 spurModel.dispose(); 509 interchangeModel.dispose(); 510 stagingModel.dispose(); 511 512 if (yef != null) { 513 yef.dispose(); 514 } 515 if (sef != null) { 516 sef.dispose(); 517 } 518 if (ief != null) { 519 ief.dispose(); 520 } 521 if (stef != null) { 522 stef.dispose(); 523 } 524 525 locationManager.deregister(location); 526 _location = null; 527 selectCheckboxes(false); 528 enableCheckboxes(false); 529 enableButtons(false); 530 } 531 532 private void saveLocation() { 533 if (!checkName(Bundle.getMessage("save"))) { 534 return; 535 } 536 // stop table editing so "Moves" are properly saved 537 if (spurTable.isEditing()) { 538 spurTable.getCellEditor().stopCellEditing(); 539 } 540 if (yardTable.isEditing()) { 541 yardTable.getCellEditor().stopCellEditing(); 542 } 543 if (interchangeTable.isEditing()) { 544 interchangeTable.getCellEditor().stopCellEditing(); 545 } 546 if (stagingTable.isEditing()) { 547 stagingTable.getCellEditor().stopCellEditing(); 548 } 549 _location.setName(locationNameTextField.getText()); 550 _location.setComment(TrainCommon.formatColorString(commentTextArea.getText(), commentColorChooser.getColor())); 551 _location.setDivision((Division) divisionComboBox.getSelectedItem()); 552 if (Setup.isRfidEnabled() && readerSelector != null) { 553 _location.setReporter(readerSelector.getSelectedItem()); 554 } 555 // save location file 556 OperationsXml.save(); 557 } 558 559 /** 560 * @return true if name OK and is less than the maximum allowed length 561 */ 562 private boolean checkName(String s) { 563 String locationName = locationNameTextField.getText().trim(); 564 if (locationName.isEmpty()) { 565 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MustEnterName"), 566 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 567 return false; 568 } 569 // hyphen feature needs at least one character to work properly 570 if (locationName.contains(TrainCommon.HYPHEN)) { 571 String[] check = locationName.split(TrainCommon.HYPHEN); 572 if (check.length == 0) { 573 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("HyphenFeature"), 574 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 575 return false; 576 } 577 locationName = check[0]; 578 } 579 if (TrainCommon.splitString(locationName).length() > MAX_NAME_LENGTH) { 580 // log.error("Location name must be less than "+ 581 // Integer.toString(MAX_NAME_LENGTH+1) +" characters"); 582 JmriJOptionPane.showMessageDialog(this, 583 Bundle.getMessage("LocationNameLengthMax", Integer.toString(MAX_NAME_LENGTH + 1)), 584 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 585 return false; 586 } 587 if (!OperationsXml.checkFileName(locationName)) { // NOI18N 588 JmriJOptionPane.showMessageDialog(this, 589 Bundle.getMessage("NameResChar") + NEW_LINE + Bundle.getMessage("ReservedChar"), 590 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 591 return false; 592 } 593 return true; 594 } 595 596 private void reportLocationExists(String s) { 597 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("LocationAlreadyExists"), 598 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 599 } 600 601 private void enableButtons(boolean enabled) { 602 toolMenu.setEnabled(enabled); 603 northCheckBox.setEnabled(enabled); 604 southCheckBox.setEnabled(enabled); 605 eastCheckBox.setEnabled(enabled); 606 westCheckBox.setEnabled(enabled); 607 divisionComboBox.setEnabled(enabled); 608 editDivisionButton.setEnabled(enabled); 609 clearButton.setEnabled(enabled); 610 setButton.setEnabled(enabled); 611 autoSelectButton.setEnabled(enabled); 612 addYardButton.setEnabled(enabled); 613 addSpurButton.setEnabled(enabled); 614 addInterchangeButton.setEnabled(enabled); 615 addStagingButton.setEnabled(enabled); 616 saveLocationButton.setEnabled(enabled); 617 deleteLocationButton.setEnabled(enabled); 618 // the inverse! 619 addLocationButton.setEnabled(!enabled); 620 // enable radio buttons 621 spurRadioButton.setEnabled(enabled); 622 yardRadioButton.setEnabled(enabled); 623 interchangeRadioButton.setEnabled(enabled); 624 stagingRadioButton.setEnabled(enabled); 625 if (readerSelector != null) { 626 // enable readerSelect. 627 readerSelector.setEnabled(enabled && Setup.isRfidEnabled()); 628 } 629 } 630 631 @Override 632 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 633 setVisibleTrackType(); 634 } 635 636 private void setVisibleTrackType() { 637 enableTrackTypeRadioButtons(); 638 interchangePane.setVisible(interchangeRadioButton.isSelected()); 639 addInterchangeButton.setVisible(interchangeRadioButton.isSelected()); 640 stagingPane.setVisible(stagingRadioButton.isSelected()); 641 addStagingButton.setVisible(stagingRadioButton.isSelected()); 642 yardPane.setVisible(yardRadioButton.isSelected()); 643 addYardButton.setVisible(yardRadioButton.isSelected()); 644 spurPane.setVisible(spurRadioButton.isSelected()); 645 addSpurButton.setVisible(spurRadioButton.isSelected()); 646 } 647 648 private void enableTrackTypeRadioButtons() { 649 if (spurModel.getRowCount() > 0 || yardModel.getRowCount() > 0 || interchangeModel.getRowCount() > 0) { 650 if (stagingRadioButton.isSelected()) { 651 spurRadioButton.setSelected(true); 652 } 653 stagingRadioButton.setEnabled(false); 654 } else if (stagingModel.getRowCount() > 0) { 655 stagingRadioButton.setSelected(true); 656 spurRadioButton.setEnabled(false); 657 yardRadioButton.setEnabled(false); 658 interchangeRadioButton.setEnabled(false); 659 } else if (_location != null) { 660 spurRadioButton.setEnabled(true); 661 yardRadioButton.setEnabled(true); 662 interchangeRadioButton.setEnabled(true); 663 stagingRadioButton.setEnabled(true); 664 } 665 } 666 667 private void enableCheckboxes(boolean enable) { 668 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 669 checkBox.setEnabled(enable); 670 } 671 } 672 673 /* 674 * Protected against concurrent changes by making a copy 675 * of the checkBoxes list. 676 */ 677 private void selectCheckboxes(boolean select) { 678 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 679 checkBox.setSelected(select); 680 if (_location != null) { 681 if (select) { 682 _location.addTypeName(checkBox.getText()); 683 } else { 684 _location.deleteTypeName(checkBox.getText()); 685 } 686 } 687 } 688 } 689 690 private void updateCheckboxes() { 691 x = 0; 692 y = 0; 693 checkBoxes.clear(); 694 panelCheckBoxes.removeAll(); 695 numberOfCheckBoxes = getNumberOfCheckboxesPerLine(); 696 loadTypes(InstanceManager.getDefault(CarTypes.class).getNames()); 697 698 // add space between car and loco types 699 checkNewLine(); 700 701 loadTypes(InstanceManager.getDefault(EngineTypes.class).getNames()); 702 JPanel p = new JPanel(); 703 p.add(clearButton); 704 p.add(setButton); 705 p.add(autoSelectButton); 706 GridBagConstraints gc = new GridBagConstraints(); 707 gc.gridwidth = getNumberOfCheckboxesPerLine() + 1; 708 gc.gridy = ++y; 709 panelCheckBoxes.add(p, gc); 710 panelCheckBoxes.revalidate(); 711 repaint(); 712 } 713 714 protected void updateDivisionComboBox() { 715 InstanceManager.getDefault(DivisionManager.class).updateComboBox(divisionComboBox); 716 if (_location != null) { 717 divisionComboBox.setSelectedItem(_location.getDivision()); 718 } 719 } 720 721 int x = 0; 722 int y = 0; // vertical position in panel 723 724 private void loadTypes(String[] types) { 725 for (String type : types) { 726 JCheckBox checkBox = new JCheckBox(); 727 checkBoxes.add(checkBox); 728 checkBox.setText(type); 729 addCheckBoxAction(checkBox); 730 addItemLeft(panelCheckBoxes, checkBox, x, y); 731 if (_location != null) { 732 if (_location.acceptsTypeName(type)) { 733 checkBox.setSelected(true); 734 } 735 } else { 736 checkBox.setEnabled(false); 737 } 738 checkNewLine(); 739 } 740 } 741 742 int numberOfCheckBoxes; 743 744 private void checkNewLine() { 745 if (++x > numberOfCheckBoxes) { 746 y++; 747 x = 0; 748 } 749 } 750 751 /** 752 * Adjust the location's car service types to only reflect the car types 753 * serviced by the location's tracks. Protected against concurrent changes by 754 * creating a new list of checkboxes. 755 */ 756 private void autoSelectCheckboxes() { 757 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 758 checkBox.setSelected(false); 759 // check each track to determine which car types are serviced by 760 // this location 761 List<Track> tracks = _location.getTracksList(); 762 for (Track track : tracks) { 763 if (track.isTypeNameAccepted(checkBox.getText())) { 764 checkBox.setSelected(true); 765 } 766 } 767 // this type of car isn't serviced by any of the tracks, so delete 768 if (!checkBox.isSelected()) { 769 _location.deleteTypeName(checkBox.getText()); 770 } 771 } 772 } 773 774 LocationsByCarTypeFrame lctf = null; 775 776 @Override 777 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 778 JCheckBox b = (JCheckBox) ae.getSource(); 779 log.debug("checkbox change {}", b.getText()); 780 if (_location == null) { 781 return; 782 } 783 _location.removePropertyChangeListener(this); 784 if (b.isSelected()) { 785 _location.addTypeName(b.getText()); 786 // show which tracks will service this car type 787 if (InstanceManager.getDefault(CarTypes.class).containsName(b.getText())) { 788 if (lctf != null) { 789 lctf.dispose(); 790 } 791 lctf = new LocationsByCarTypeFrame(); 792 lctf.initComponents(_location, b.getText()); 793 } 794 } else { 795 _location.deleteTypeName(b.getText()); 796 } 797 _location.addPropertyChangeListener(this); 798 } 799 800 private void addCheckBoxTrainAction(JCheckBox b) { 801 b.addActionListener(new java.awt.event.ActionListener() { 802 @Override 803 public void actionPerformed(java.awt.event.ActionEvent e) { 804 checkBoxActionTrainPerformed(e); 805 } 806 }); 807 } 808 809 private void checkBoxActionTrainPerformed(java.awt.event.ActionEvent ae) { 810 // save train directions serviced by this location 811 if (_location == null) { 812 return; 813 } 814 int direction = 0; 815 if (northCheckBox.isSelected()) { 816 direction += Location.NORTH; 817 } 818 if (southCheckBox.isSelected()) { 819 direction += Location.SOUTH; 820 } 821 if (eastCheckBox.isSelected()) { 822 direction += Location.EAST; 823 } 824 if (westCheckBox.isSelected()) { 825 direction += Location.WEST; 826 } 827 _location.setTrainDirections(direction); 828 829 } 830 831 private void setTrainDirectionBoxes() { 832 northCheckBox.setVisible((Setup.getTrainDirection() & Setup.NORTH) == Setup.NORTH); 833 southCheckBox.setVisible((Setup.getTrainDirection() & Setup.SOUTH) == Setup.SOUTH); 834 eastCheckBox.setVisible((Setup.getTrainDirection() & Setup.EAST) == Setup.EAST); 835 westCheckBox.setVisible((Setup.getTrainDirection() & Setup.WEST) == Setup.WEST); 836 837 northCheckBox.setSelected((_location.getTrainDirections() & Location.NORTH) == Location.NORTH); 838 southCheckBox.setSelected((_location.getTrainDirections() & Location.SOUTH) == Location.SOUTH); 839 eastCheckBox.setSelected((_location.getTrainDirections() & Location.EAST) == Location.EAST); 840 westCheckBox.setSelected((_location.getTrainDirections() & Location.WEST) == Location.WEST); 841 } 842 843 @Override 844 protected void comboBoxActionPerformed(ActionEvent ae) { 845 setDivisionButtonText(); 846 } 847 848 private void setDivisionButtonText() { 849 if (divisionComboBox.getSelectedItem() == null) { 850 editDivisionButton.setText(Bundle.getMessage("Add")); 851 } else { 852 editDivisionButton.setText(Bundle.getMessage("ButtonEdit")); 853 } 854 } 855 856 @Override 857 public void dispose() { 858 if (_location != null) { 859 _location.removePropertyChangeListener(this); 860 } 861 InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this); 862 InstanceManager.getDefault(EngineTypes.class).removePropertyChangeListener(this); 863 yardModel.dispose(); 864 spurModel.dispose(); 865 interchangeModel.dispose(); 866 stagingModel.dispose(); 867 if (lctf != null) { 868 lctf.dispose(); 869 } 870 if (yef != null) { 871 yef.dispose(); 872 } 873 if (sef != null) { 874 sef.dispose(); 875 } 876 if (ief != null) { 877 ief.dispose(); 878 } 879 if (stef != null) { 880 stef.dispose(); 881 } 882 super.dispose(); 883 } 884 885 @Override 886 public void propertyChange(java.beans.PropertyChangeEvent e) { 887 if (Control.SHOW_PROPERTY) { 888 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), 889 e.getNewValue()); 890 } 891 if (e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY) || 892 e.getPropertyName().equals(EngineTypes.ENGINETYPES_CHANGED_PROPERTY) || 893 e.getPropertyName().equals(Location.TYPES_CHANGED_PROPERTY)) { 894 updateCheckboxes(); 895 } 896 if (e.getPropertyName().equals(DivisionManager.LISTLENGTH_CHANGED_PROPERTY)) { 897 updateDivisionComboBox(); 898 } 899 if (e.getPropertyName().equals(Setup.TRAIN_DIRECTION_PROPERTY_CHANGE)) { 900 setTrainDirectionBoxes(); 901 } 902 } 903 904 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LocationEditFrame.class); 905}