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