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