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