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(); 410 yef.initComponents(_location, null); 411 } 412 if (ae.getSource() == addSpurButton) { 413 sef = new SpurEditFrame(); 414 sef.initComponents(_location, null); 415 } 416 if (ae.getSource() == addInterchangeButton) { 417 ief = new InterchangeEditFrame(); 418 ief.initComponents(_location, null); 419 } 420 if (ae.getSource() == addStagingButton) { 421 stef = new StagingEditFrame(); 422 stef.initComponents(_location, null); 423 } 424 425 if (ae.getSource() == saveLocationButton) { 426 log.debug("location save button activated"); 427 Location l = locationManager.getLocationByName(locationNameTextField.getText()); 428 if (_location == null && l == null) { 429 saveNewLocation(); 430 } else { 431 if (l != null && l != _location) { 432 reportLocationExists(Bundle.getMessage("save")); 433 return; 434 } 435 saveLocation(); 436 if (Setup.isCloseWindowOnSaveEnabled()) { 437 dispose(); 438 } 439 } 440 } 441 if (ae.getSource() == deleteLocationButton) { 442 log.debug("location delete button activated"); 443 deleteLocation(); 444 // save location file 445 OperationsXml.save(); 446 } 447 if (ae.getSource() == addLocationButton) { 448 Location l = locationManager.getLocationByName(locationNameTextField.getText()); 449 if (l != null) { 450 reportLocationExists(Bundle.getMessage("add")); 451 return; 452 } 453 saveNewLocation(); 454 } 455 if (ae.getSource() == setButton) { 456 selectCheckboxes(true); 457 } 458 if (ae.getSource() == clearButton) { 459 selectCheckboxes(false); 460 } 461 if (ae.getSource() == autoSelectButton) { 462 log.debug("auto select button pressed"); 463 if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("autoSelectCarTypes?"), 464 Bundle.getMessage("autoSelectLocations?"), 465 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 466 return; 467 } 468 autoSelectCheckboxes(); 469 } 470 } 471 472 private void saveNewLocation() { 473 if (!checkName(Bundle.getMessage("add"))) { 474 return; 475 } 476 Location location = locationManager.newLocation(locationNameTextField.getText()); 477 yardModel.initTable(yardTable, location); 478 spurModel.initTable(spurTable, location); 479 interchangeModel.initTable(interchangeTable, location); 480 stagingModel.initTable(stagingTable, location); 481 _location = location; 482 _location.addPropertyChangeListener(this); 483 484 updateCheckboxes(); 485 enableButtons(true); 486 setTrainDirectionBoxes(); 487 saveLocation(); 488 loadToolMenu(); 489 } 490 491 private void deleteLocation() { 492 Location location = locationManager.getLocationByName(locationNameTextField.getText()); 493 if (location == null) { 494 return; 495 } 496 // check to see if any route uses this location 497 Route route = InstanceManager.getDefault(RouteManager.class).isLocationInUse(location); 498 if (route != null) { 499 JmriJOptionPane.showMessageDialog(this, 500 Bundle.getMessage("RouteUsesLocation", route.getName(), location.getName()), 501 Bundle.getMessage("CanNotDeleteLocation"), JmriJOptionPane.ERROR_MESSAGE); 502 // show all the routes using this location 503 ShowRoutesServingLocationFrame frame = new ShowRoutesServingLocationFrame(); 504 frame.initComponents(location); 505 return; 506 } 507 int count = location.getNumberRS(); 508 if (count > 0) { 509 if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("ThereAreCars", Integer.toString(count)), 510 Bundle.getMessage("deletelocation?"), 511 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 512 return; 513 } 514 } else { 515 if (JmriJOptionPane.showConfirmDialog(this, 516 Bundle.getMessage("DoYouWantToDeleteLocation", locationNameTextField.getText()), 517 Bundle.getMessage("deletelocation?"), 518 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 519 return; 520 } 521 } 522 523 yardModel.dispose(); 524 spurModel.dispose(); 525 interchangeModel.dispose(); 526 stagingModel.dispose(); 527 528 if (yef != null) { 529 yef.dispose(); 530 } 531 if (sef != null) { 532 sef.dispose(); 533 } 534 if (ief != null) { 535 ief.dispose(); 536 } 537 if (stef != null) { 538 stef.dispose(); 539 } 540 541 locationManager.deregister(location); 542 _location = null; 543 selectCheckboxes(false); 544 enableCheckboxes(false); 545 enableButtons(false); 546 } 547 548 private void saveLocation() { 549 if (!checkName(Bundle.getMessage("save"))) { 550 return; 551 } 552 // stop table editing so "Moves" are properly saved 553 if (spurTable.isEditing()) { 554 spurTable.getCellEditor().stopCellEditing(); 555 } 556 if (yardTable.isEditing()) { 557 yardTable.getCellEditor().stopCellEditing(); 558 } 559 if (interchangeTable.isEditing()) { 560 interchangeTable.getCellEditor().stopCellEditing(); 561 } 562 if (stagingTable.isEditing()) { 563 stagingTable.getCellEditor().stopCellEditing(); 564 } 565 _location.setName(locationNameTextField.getText()); 566 _location.setComment(TrainCommon.formatColorString(commentTextArea.getText(), commentColorChooser.getColor(), 567 boldCheckBox.isSelected())); 568 _location.setDivision((Division) divisionComboBox.getSelectedItem()); 569 if (Setup.isRfidEnabled() && readerSelector != null) { 570 _location.setReporter(readerSelector.getSelectedItem()); 571 } 572 // save location file 573 OperationsXml.save(); 574 } 575 576 /** 577 * @return true if name OK and is less than the maximum allowed length 578 */ 579 private boolean checkName(String s) { 580 String locationName = locationNameTextField.getText().trim(); 581 if (locationName.isEmpty()) { 582 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MustEnterName"), 583 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 584 return false; 585 } 586 // hyphen feature needs at least one character to work properly 587 if (locationName.contains(TrainCommon.HYPHEN)) { 588 String[] check = locationName.split(TrainCommon.HYPHEN); 589 if (check.length == 0) { 590 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("HyphenFeature"), 591 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 592 return false; 593 } 594 locationName = check[0]; 595 } 596 if (TrainCommon.splitString(locationName).length() > MAX_NAME_LENGTH) { 597 // log.error("Location name must be less than "+ 598 // Integer.toString(MAX_NAME_LENGTH+1) +" characters"); 599 JmriJOptionPane.showMessageDialog(this, 600 Bundle.getMessage("LocationNameLengthMax", Integer.toString(MAX_NAME_LENGTH + 1)), 601 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 602 return false; 603 } 604 if (!OperationsXml.checkFileName(locationName)) { // NOI18N 605 JmriJOptionPane.showMessageDialog(this, 606 Bundle.getMessage("NameResChar") + NEW_LINE + Bundle.getMessage("ReservedChar"), 607 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 608 return false; 609 } 610 return true; 611 } 612 613 private void reportLocationExists(String s) { 614 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("LocationAlreadyExists"), 615 Bundle.getMessage("CanNotLocation", s), JmriJOptionPane.ERROR_MESSAGE); 616 } 617 618 private void enableButtons(boolean enabled) { 619 toolMenu.setEnabled(enabled); 620 northCheckBox.setEnabled(enabled); 621 southCheckBox.setEnabled(enabled); 622 eastCheckBox.setEnabled(enabled); 623 westCheckBox.setEnabled(enabled); 624 divisionComboBox.setEnabled(enabled); 625 editDivisionButton.setEnabled(enabled); 626 clearButton.setEnabled(enabled); 627 setButton.setEnabled(enabled); 628 autoSelectButton.setEnabled(enabled); 629 addYardButton.setEnabled(enabled); 630 addSpurButton.setEnabled(enabled); 631 addInterchangeButton.setEnabled(enabled); 632 addStagingButton.setEnabled(enabled); 633 saveLocationButton.setEnabled(enabled); 634 deleteLocationButton.setEnabled(enabled); 635 // the inverse! 636 addLocationButton.setEnabled(!enabled); 637 // enable radio buttons 638 spurRadioButton.setEnabled(enabled); 639 yardRadioButton.setEnabled(enabled); 640 interchangeRadioButton.setEnabled(enabled); 641 stagingRadioButton.setEnabled(enabled); 642 if (readerSelector != null) { 643 // enable readerSelect. 644 readerSelector.setEnabled(enabled && Setup.isRfidEnabled()); 645 } 646 } 647 648 @Override 649 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 650 setVisibleTrackType(); 651 } 652 653 private void setVisibleTrackType() { 654 enableTrackTypeRadioButtons(); 655 interchangePane.setVisible(interchangeRadioButton.isSelected()); 656 addInterchangeButton.setVisible(interchangeRadioButton.isSelected()); 657 stagingPane.setVisible(stagingRadioButton.isSelected()); 658 addStagingButton.setVisible(stagingRadioButton.isSelected()); 659 yardPane.setVisible(yardRadioButton.isSelected()); 660 addYardButton.setVisible(yardRadioButton.isSelected()); 661 spurPane.setVisible(spurRadioButton.isSelected()); 662 addSpurButton.setVisible(spurRadioButton.isSelected()); 663 } 664 665 private void enableTrackTypeRadioButtons() { 666 if (spurModel.getRowCount() > 0 || yardModel.getRowCount() > 0 || interchangeModel.getRowCount() > 0) { 667 if (stagingRadioButton.isSelected()) { 668 spurRadioButton.setSelected(true); 669 } 670 stagingRadioButton.setEnabled(false); 671 } else if (stagingModel.getRowCount() > 0) { 672 stagingRadioButton.setSelected(true); 673 spurRadioButton.setEnabled(false); 674 yardRadioButton.setEnabled(false); 675 interchangeRadioButton.setEnabled(false); 676 } else if (_location != null) { 677 spurRadioButton.setEnabled(true); 678 yardRadioButton.setEnabled(true); 679 interchangeRadioButton.setEnabled(true); 680 stagingRadioButton.setEnabled(true); 681 } 682 } 683 684 private void enableCheckboxes(boolean enable) { 685 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 686 checkBox.setEnabled(enable); 687 } 688 } 689 690 /* 691 * Protected against concurrent changes by making a copy of the checkBoxes 692 * list. 693 */ 694 private void selectCheckboxes(boolean select) { 695 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 696 checkBox.setSelected(select); 697 if (_location != null) { 698 if (select) { 699 _location.addTypeName(checkBox.getText()); 700 } else { 701 _location.deleteTypeName(checkBox.getText()); 702 } 703 } 704 } 705 } 706 707 private void updateCheckboxes() { 708 x = 0; 709 y = 0; 710 checkBoxes.clear(); 711 panelCheckBoxes.removeAll(); 712 numberOfCheckBoxes = getNumberOfCheckboxesPerLine(); 713 loadTypes(InstanceManager.getDefault(CarTypes.class).getNames()); 714 715 // add space between car and loco types 716 checkNewLine(); 717 718 loadTypes(InstanceManager.getDefault(EngineTypes.class).getNames()); 719 JPanel p = new JPanel(); 720 p.add(clearButton); 721 p.add(setButton); 722 p.add(autoSelectButton); 723 GridBagConstraints gc = new GridBagConstraints(); 724 gc.gridwidth = getNumberOfCheckboxesPerLine() + 1; 725 gc.gridy = ++y; 726 panelCheckBoxes.add(p, gc); 727 panelCheckBoxes.revalidate(); 728 repaint(); 729 } 730 731 protected void updateDivisionComboBox() { 732 InstanceManager.getDefault(DivisionManager.class).updateComboBox(divisionComboBox); 733 if (_location != null) { 734 divisionComboBox.setSelectedItem(_location.getDivision()); 735 } 736 } 737 738 int x = 0; 739 int y = 0; // vertical position in panel 740 741 private void loadTypes(String[] types) { 742 for (String type : types) { 743 JCheckBox checkBox = new JCheckBox(); 744 checkBoxes.add(checkBox); 745 checkBox.setText(type); 746 addCheckBoxAction(checkBox); 747 addItemLeft(panelCheckBoxes, checkBox, x, y); 748 if (_location != null) { 749 if (_location.acceptsTypeName(type)) { 750 checkBox.setSelected(true); 751 } 752 } else { 753 checkBox.setEnabled(false); 754 } 755 checkNewLine(); 756 } 757 } 758 759 int numberOfCheckBoxes; 760 761 private void checkNewLine() { 762 if (++x > numberOfCheckBoxes) { 763 y++; 764 x = 0; 765 } 766 } 767 768 /** 769 * Adjust the location's car service types to only reflect the car types 770 * serviced by the location's tracks. Protected against concurrent changes 771 * by creating a new list of checkboxes. 772 */ 773 private void autoSelectCheckboxes() { 774 for (JCheckBox checkBox : new ArrayList<>(checkBoxes)) { 775 checkBox.setSelected(false); 776 // check each track to determine which car types are serviced by 777 // this location 778 List<Track> tracks = _location.getTracksList(); 779 for (Track track : tracks) { 780 if (track.isTypeNameAccepted(checkBox.getText())) { 781 checkBox.setSelected(true); 782 } 783 } 784 // this type of car isn't serviced by any of the tracks, so delete 785 if (!checkBox.isSelected()) { 786 _location.deleteTypeName(checkBox.getText()); 787 } 788 } 789 } 790 791 LocationsByCarTypeFrame lctf = null; 792 793 @Override 794 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 795 JCheckBox b = (JCheckBox) ae.getSource(); 796 log.debug("checkbox change {}", b.getText()); 797 if (_location == null) { 798 return; 799 } 800 _location.removePropertyChangeListener(this); 801 if (b.isSelected()) { 802 _location.addTypeName(b.getText()); 803 // show which tracks will service this car type 804 if (InstanceManager.getDefault(CarTypes.class).containsName(b.getText())) { 805 if (lctf != null) { 806 lctf.dispose(); 807 } 808 lctf = new LocationsByCarTypeFrame(); 809 lctf.initComponents(_location, b.getText()); 810 } 811 } else { 812 _location.deleteTypeName(b.getText()); 813 } 814 _location.addPropertyChangeListener(this); 815 } 816 817 private void addCheckBoxTrainAction(JCheckBox b) { 818 b.addActionListener(new java.awt.event.ActionListener() { 819 @Override 820 public void actionPerformed(java.awt.event.ActionEvent e) { 821 checkBoxActionTrainPerformed(e); 822 } 823 }); 824 } 825 826 private void checkBoxActionTrainPerformed(java.awt.event.ActionEvent ae) { 827 // save train directions serviced by this location 828 if (_location == null) { 829 return; 830 } 831 int direction = 0; 832 if (northCheckBox.isSelected()) { 833 direction += Location.NORTH; 834 } 835 if (southCheckBox.isSelected()) { 836 direction += Location.SOUTH; 837 } 838 if (eastCheckBox.isSelected()) { 839 direction += Location.EAST; 840 } 841 if (westCheckBox.isSelected()) { 842 direction += Location.WEST; 843 } 844 _location.setTrainDirections(direction); 845 846 } 847 848 private void setTrainDirectionBoxes() { 849 northCheckBox.setVisible((Setup.getTrainDirection() & Setup.NORTH) == Setup.NORTH); 850 southCheckBox.setVisible((Setup.getTrainDirection() & Setup.SOUTH) == Setup.SOUTH); 851 eastCheckBox.setVisible((Setup.getTrainDirection() & Setup.EAST) == Setup.EAST); 852 westCheckBox.setVisible((Setup.getTrainDirection() & Setup.WEST) == Setup.WEST); 853 854 northCheckBox.setSelected((_location.getTrainDirections() & Location.NORTH) == Location.NORTH); 855 southCheckBox.setSelected((_location.getTrainDirections() & Location.SOUTH) == Location.SOUTH); 856 eastCheckBox.setSelected((_location.getTrainDirections() & Location.EAST) == Location.EAST); 857 westCheckBox.setSelected((_location.getTrainDirections() & Location.WEST) == Location.WEST); 858 } 859 860 @Override 861 protected void comboBoxActionPerformed(ActionEvent ae) { 862 setDivisionButtonText(); 863 } 864 865 private void setDivisionButtonText() { 866 if (divisionComboBox.getSelectedItem() == null) { 867 editDivisionButton.setText(Bundle.getMessage("Add")); 868 } else { 869 editDivisionButton.setText(Bundle.getMessage("ButtonEdit")); 870 } 871 } 872 873 @Override 874 public void dispose() { 875 if (_location != null) { 876 _location.removePropertyChangeListener(this); 877 } 878 InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this); 879 InstanceManager.getDefault(EngineTypes.class).removePropertyChangeListener(this); 880 yardModel.dispose(); 881 spurModel.dispose(); 882 interchangeModel.dispose(); 883 stagingModel.dispose(); 884 if (lctf != null) { 885 lctf.dispose(); 886 } 887 if (yef != null) { 888 yef.dispose(); 889 } 890 if (sef != null) { 891 sef.dispose(); 892 } 893 if (ief != null) { 894 ief.dispose(); 895 } 896 if (stef != null) { 897 stef.dispose(); 898 } 899 super.dispose(); 900 } 901 902 @Override 903 public void propertyChange(java.beans.PropertyChangeEvent e) { 904 if (Control.SHOW_PROPERTY) { 905 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), 906 e.getNewValue()); 907 } 908 if (e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY) || 909 e.getPropertyName().equals(EngineTypes.ENGINETYPES_CHANGED_PROPERTY) || 910 e.getPropertyName().equals(Location.TYPES_CHANGED_PROPERTY)) { 911 updateCheckboxes(); 912 } 913 if (e.getPropertyName().equals(DivisionManager.LISTLENGTH_CHANGED_PROPERTY)) { 914 updateDivisionComboBox(); 915 } 916 if (e.getPropertyName().equals(Setup.TRAIN_DIRECTION_PROPERTY_CHANGE)) { 917 setTrainDirectionBoxes(); 918 } 919 } 920 921 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LocationEditFrame.class); 922}