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