001package jmri.jmrit.operations.trains; 002 003import java.awt.Dimension; 004import java.awt.FlowLayout; 005import java.awt.GridBagLayout; 006import javax.swing.BorderFactory; 007import javax.swing.BoxLayout; 008import javax.swing.ButtonGroup; 009import javax.swing.JButton; 010import javax.swing.JComboBox; 011import javax.swing.JLabel; 012import javax.swing.JPanel; 013import javax.swing.JRadioButton; 014import javax.swing.JScrollPane; 015import jmri.InstanceManager; 016import jmri.jmrit.operations.OperationsFrame; 017import jmri.jmrit.operations.OperationsXml; 018import jmri.jmrit.operations.rollingstock.cars.CarRoads; 019import jmri.jmrit.operations.rollingstock.cars.CarTypes; 020import jmri.jmrit.operations.setup.Control; 021import jmri.jmrit.operations.setup.Setup; 022import org.slf4j.Logger; 023import org.slf4j.LoggerFactory; 024 025/** 026 * Frame for user edit of a train's road options 027 * 028 * @author Dan Boudreau Copyright (C) 2013, 2022 029 * 030 */ 031public class TrainRoadOptionsFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 032 033 Train _train = null; 034 035 JPanel pCarRoadControls = new JPanel(); 036 JPanel panelCarRoads = new JPanel(); 037 JScrollPane paneCarRoads = new JScrollPane(panelCarRoads); 038 039 JPanel pLocoRoadControls = new JPanel(); 040 JPanel panelLocoRoads = new JPanel(); 041 JScrollPane paneLocoRoads = new JScrollPane(panelLocoRoads); 042 043 // labels 044 JLabel trainName = new JLabel(); 045 JLabel trainDescription = new JLabel(); 046 047 // major buttons 048 JButton addCarRoadButton = new JButton(Bundle.getMessage("AddRoad")); 049 JButton deleteCarRoadButton = new JButton(Bundle.getMessage("DeleteRoad")); 050 JButton deleteCarAllRoadsButton = new JButton(Bundle.getMessage("DeleteAll")); 051 JButton addLocoRoadButton = new JButton(Bundle.getMessage("AddRoad")); 052 JButton deleteLocoRoadButton = new JButton(Bundle.getMessage("DeleteRoad")); 053 JButton deleteLocoAllRoadsButton = new JButton(Bundle.getMessage("DeleteAll")); 054 055 JButton saveTrainButton = new JButton(Bundle.getMessage("SaveTrain")); 056 057 // radio buttons 058 JRadioButton carRoadNameAll = new JRadioButton(Bundle.getMessage("AcceptAll")); 059 JRadioButton carRoadNameInclude = new JRadioButton(Bundle.getMessage("AcceptOnly")); 060 JRadioButton carRoadNameExclude = new JRadioButton(Bundle.getMessage("Exclude")); 061 JRadioButton locoRoadNameAll = new JRadioButton(Bundle.getMessage("AcceptAll")); 062 JRadioButton locoRoadNameInclude = new JRadioButton(Bundle.getMessage("AcceptOnly")); 063 JRadioButton locoRoadNameExclude = new JRadioButton(Bundle.getMessage("Exclude")); 064 065 // combo boxes 066 JComboBox<String> comboBoxCarRoads = InstanceManager.getDefault(CarRoads.class).getComboBox(); 067 JComboBox<String> comboBoxLocoRoads = InstanceManager.getDefault(CarRoads.class).getComboBox(); 068 069 public static final String DISPOSE = "dispose"; // NOI18N 070 071 public TrainRoadOptionsFrame() { 072 super(Bundle.getMessage("MenuItemRoadOptions")); 073 } 074 075 public void initComponents(TrainEditFrame parent) { 076 077 parent.setChildFrame(this); 078 _train = parent._train; 079 080 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 081 082 // Layout the panel by rows 083 JPanel p1 = new JPanel(); 084 p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 085 p1.setMaximumSize(new Dimension(2000, 250)); 086 087 // Layout the panel by rows 088 // row 1a 089 JPanel pName = new JPanel(); 090 pName.setLayout(new GridBagLayout()); 091 pName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Name"))); 092 addItem(pName, trainName, 0, 0); 093 094 // row 1b 095 JPanel pDesc = new JPanel(); 096 pDesc.setLayout(new GridBagLayout()); 097 pDesc.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Description"))); 098 addItem(pDesc, trainDescription, 0, 0); 099 100 p1.add(pName); 101 p1.add(pDesc); 102 103 // row 3 Car Roads 104 JPanel pCarRoad = new JPanel(); 105 pCarRoad.setLayout(new BoxLayout(pCarRoad, BoxLayout.Y_AXIS)); 106 JScrollPane paneCar = new JScrollPane(pCarRoad); 107 paneCar.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("CarRoadsTrain"))); 108 paneCar.setMaximumSize(new Dimension(2000, 400)); 109 110 JPanel pCarRoadRadioButtons = new JPanel(); 111 pCarRoadRadioButtons.setLayout(new FlowLayout()); 112 113 pCarRoadRadioButtons.add(carRoadNameAll); 114 pCarRoadRadioButtons.add(carRoadNameInclude); 115 pCarRoadRadioButtons.add(carRoadNameExclude); 116 117 pCarRoadControls.setLayout(new FlowLayout()); 118 119 pCarRoadControls.add(comboBoxCarRoads); 120 pCarRoadControls.add(addCarRoadButton); 121 pCarRoadControls.add(deleteCarRoadButton); 122 pCarRoadControls.add(deleteCarAllRoadsButton); 123 124 pCarRoadControls.setVisible(false); 125 126 pCarRoad.add(pCarRoadRadioButtons); 127 pCarRoad.add(pCarRoadControls); 128 129 // row 4 130 panelCarRoads.setLayout(new GridBagLayout()); 131 paneCarRoads.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Roads"))); 132 133 ButtonGroup carRoadGroup = new ButtonGroup(); 134 carRoadGroup.add(carRoadNameAll); 135 carRoadGroup.add(carRoadNameInclude); 136 carRoadGroup.add(carRoadNameExclude); 137 138 // row 5 Engine Roads 139 JPanel pLocoRoad = new JPanel(); 140 pLocoRoad.setLayout(new BoxLayout(pLocoRoad, BoxLayout.Y_AXIS)); 141 JScrollPane paneLoco = new JScrollPane(pLocoRoad); 142 paneLoco.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LocoRoadsTrain"))); 143 paneLoco.setMaximumSize(new Dimension(2000, 400)); 144 145 JPanel pLocoRoadRadioButtons = new JPanel(); 146 pLocoRoadRadioButtons.setLayout(new FlowLayout()); 147 148 pLocoRoadRadioButtons.add(locoRoadNameAll); 149 pLocoRoadRadioButtons.add(locoRoadNameInclude); 150 pLocoRoadRadioButtons.add(locoRoadNameExclude); 151 152 pLocoRoadControls.setLayout(new FlowLayout()); 153 154 pLocoRoadControls.add(comboBoxLocoRoads); 155 pLocoRoadControls.add(addLocoRoadButton); 156 pLocoRoadControls.add(deleteLocoRoadButton); 157 pLocoRoadControls.add(deleteLocoAllRoadsButton); 158 159 pLocoRoadControls.setVisible(false); 160 161 pLocoRoad.add(pLocoRoadRadioButtons); 162 pLocoRoad.add(pLocoRoadControls); 163 164 // row 4 165 panelLocoRoads.setLayout(new GridBagLayout()); 166 paneLocoRoads.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Roads"))); 167 168 ButtonGroup locoRoadGroup = new ButtonGroup(); 169 locoRoadGroup.add(locoRoadNameAll); 170 locoRoadGroup.add(locoRoadNameInclude); 171 locoRoadGroup.add(locoRoadNameExclude); 172 173 // row 12 174 JPanel panelButtons = new JPanel(); 175 panelButtons.setLayout(new GridBagLayout()); 176 panelButtons.setBorder(BorderFactory.createTitledBorder("")); 177 panelButtons.setMaximumSize(new Dimension(2000, 200)); 178 179 // row 13 180 addItem(panelButtons, saveTrainButton, 0, 0); 181 182 getContentPane().add(p1); 183 getContentPane().add(paneCar); 184 getContentPane().add(paneCarRoads); 185 getContentPane().add(paneLoco); 186 getContentPane().add(paneLocoRoads); 187 getContentPane().add(panelButtons); 188 189 // setup buttons 190 addButtonAction(saveTrainButton); 191 192 addButtonAction(deleteCarRoadButton); 193 addButtonAction(deleteCarAllRoadsButton); 194 addButtonAction(addCarRoadButton); 195 196 addRadioButtonAction(carRoadNameAll); 197 addRadioButtonAction(carRoadNameInclude); 198 addRadioButtonAction(carRoadNameExclude); 199 200 addButtonAction(deleteLocoRoadButton); 201 addButtonAction(deleteLocoAllRoadsButton); 202 addButtonAction(addLocoRoadButton); 203 204 addRadioButtonAction(locoRoadNameAll); 205 addRadioButtonAction(locoRoadNameInclude); 206 addRadioButtonAction(locoRoadNameExclude); 207 208 if (_train != null) { 209 trainName.setText(_train.getName()); 210 trainDescription.setText(_train.getDescription()); 211 updateButtons(true); 212 // listen for train changes 213 _train.addPropertyChangeListener(this); 214 } else { 215 updateButtons(false); 216 } 217 addHelpMenu("package.jmri.jmrit.operations.Operations_TrainRoadOptions", true); // NOI18N 218 updateRoadComboBoxes(); 219 updateCarRoadNames(); 220 updateLocoRoadNames(); 221 222 // get notified if car roads, roads, and owners gets modified 223 InstanceManager.getDefault(CarTypes.class).addPropertyChangeListener(this); 224 InstanceManager.getDefault(CarRoads.class).addPropertyChangeListener(this); 225 226 initMinimumSize(new Dimension(Control.panelWidth500, Control.panelHeight500)); 227 } 228 229 // Save 230 @Override 231 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 232 if (_train != null) { 233 if (ae.getSource() == saveTrainButton) { 234 log.debug("train save button activated"); 235 saveTrain(); 236 } 237 if (ae.getSource() == addCarRoadButton) { 238 String roadName = (String) comboBoxCarRoads.getSelectedItem(); 239 if (_train.addCarRoadName(roadName)) { 240 updateCarRoadNames(); 241 } 242 selectNextItemComboBox(comboBoxCarRoads); 243 } 244 if (ae.getSource() == deleteCarRoadButton) { 245 String roadName = (String) comboBoxCarRoads.getSelectedItem(); 246 if (_train.deleteCarRoadName(roadName)) { 247 updateCarRoadNames(); 248 } 249 selectNextItemComboBox(comboBoxCarRoads); 250 } 251 if (ae.getSource() == deleteCarAllRoadsButton) { 252 deleteAllCarRoads(); 253 } 254 if (ae.getSource() == addLocoRoadButton) { 255 String roadName = (String) comboBoxLocoRoads.getSelectedItem(); 256 if (_train.addLocoRoadName(roadName)) { 257 updateLocoRoadNames(); 258 } 259 selectNextItemComboBox(comboBoxLocoRoads); 260 } 261 if (ae.getSource() == deleteLocoRoadButton) { 262 String roadName = (String) comboBoxLocoRoads.getSelectedItem(); 263 if (_train.deleteLocoRoadName(roadName)) { 264 updateLocoRoadNames(); 265 } 266 selectNextItemComboBox(comboBoxLocoRoads); 267 } 268 if (ae.getSource() == deleteLocoAllRoadsButton) { 269 deleteAllLocoRoads(); 270 } 271 } 272 } 273 274 @Override 275 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 276 log.debug("radio button activated"); 277 if (_train != null) { 278 if (ae.getSource() == carRoadNameAll) { 279 _train.setCarRoadOption(Train.ALL_LOADS); 280 updateCarRoadNames(); 281 } 282 if (ae.getSource() == carRoadNameInclude) { 283 _train.setCarRoadOption(Train.INCLUDE_LOADS); 284 updateCarRoadNames(); 285 } 286 if (ae.getSource() == carRoadNameExclude) { 287 _train.setCarRoadOption(Train.EXCLUDE_LOADS); 288 updateCarRoadNames(); 289 } 290 if (ae.getSource() == locoRoadNameAll) { 291 _train.setLocoRoadOption(Train.ALL_LOADS); 292 updateLocoRoadNames(); 293 } 294 if (ae.getSource() == locoRoadNameInclude) { 295 _train.setLocoRoadOption(Train.INCLUDE_LOADS); 296 updateLocoRoadNames(); 297 } 298 if (ae.getSource() == locoRoadNameExclude) { 299 _train.setLocoRoadOption(Train.EXCLUDE_LOADS); 300 updateLocoRoadNames(); 301 } 302 } 303 } 304 305 protected void updateButtons(boolean enabled) { 306 saveTrainButton.setEnabled(enabled); 307 308 carRoadNameAll.setEnabled(enabled); 309 carRoadNameInclude.setEnabled(enabled); 310 carRoadNameExclude.setEnabled(enabled); 311 312 locoRoadNameAll.setEnabled(enabled); 313 locoRoadNameInclude.setEnabled(enabled); 314 locoRoadNameExclude.setEnabled(enabled); 315 } 316 317 private static final int NUMBER_ROADS_PER_LINE = 6; 318 319 private void updateCarRoadNames() { 320 log.debug("Update car road names"); 321 panelCarRoads.removeAll(); 322 if (_train != null) { 323 // set radio button 324 carRoadNameAll.setSelected(_train.getCarRoadOption().equals(Train.ALL_LOADS)); 325 carRoadNameInclude.setSelected(_train.getCarRoadOption().equals(Train.INCLUDE_ROADS)); 326 carRoadNameExclude.setSelected(_train.getCarRoadOption().equals(Train.EXCLUDE_ROADS)); 327 328 pCarRoadControls.setVisible(!carRoadNameAll.isSelected()); 329 330 if (!carRoadNameAll.isSelected()) { 331 int x = 0; 332 int y = 0; // vertical position in panel 333 334 for (String roadName : _train.getCarRoadNames()) { 335 JLabel road = new JLabel(); 336 road.setText(roadName); 337 addItemTop(panelCarRoads, road, x++, y); 338 // limit the number of roads per line 339 if (x > NUMBER_ROADS_PER_LINE) { 340 y++; 341 x = 0; 342 } 343 } 344 revalidate(); 345 } 346 } else { 347 carRoadNameAll.setSelected(true); 348 } 349 panelCarRoads.repaint(); 350 panelCarRoads.revalidate(); 351 } 352 353 private void updateLocoRoadNames() { 354 log.debug("Update loco road names"); 355 panelLocoRoads.removeAll(); 356 if (_train != null) { 357 // set radio button 358 locoRoadNameAll.setSelected(_train.getLocoRoadOption().equals(Train.ALL_LOADS)); 359 locoRoadNameInclude.setSelected(_train.getLocoRoadOption().equals(Train.INCLUDE_ROADS)); 360 locoRoadNameExclude.setSelected(_train.getLocoRoadOption().equals(Train.EXCLUDE_ROADS)); 361 362 pLocoRoadControls.setVisible(!locoRoadNameAll.isSelected()); 363 364 if (!locoRoadNameAll.isSelected()) { 365 int x = 0; 366 int y = 0; // vertical position in panel 367 368 for (String roadName : _train.getLocoRoadNames()) { 369 JLabel road = new JLabel(); 370 road.setText(roadName); 371 addItemTop(panelLocoRoads, road, x++, y); 372 // limit the number of roads per line 373 if (x > NUMBER_ROADS_PER_LINE) { 374 y++; 375 x = 0; 376 } 377 } 378 revalidate(); 379 } 380 } else { 381 locoRoadNameAll.setSelected(true); 382 } 383 panelLocoRoads.repaint(); 384 panelLocoRoads.revalidate(); 385 } 386 387 private void deleteAllCarRoads() { 388 if (_train != null) { 389 for (String road : _train.getCarRoadNames()) { 390 _train.deleteCarRoadName(road); 391 } 392 } 393 updateCarRoadNames(); 394 } 395 396 private void deleteAllLocoRoads() { 397 if (_train != null) { 398 for (String road : _train.getLocoRoadNames()) { 399 _train.deleteLocoRoadName(road); 400 } 401 } 402 updateLocoRoadNames(); 403 } 404 405 private void saveTrain() { 406 OperationsXml.save(); 407 if (Setup.isCloseWindowOnSaveEnabled()) { 408 dispose(); 409 } 410 } 411 412 private void updateRoadComboBoxes() { 413 InstanceManager.getDefault(CarRoads.class).updateComboBox(comboBoxCarRoads); 414 InstanceManager.getDefault(CarRoads.class).updateComboBox(comboBoxLocoRoads); 415 } 416 417 @Override 418 public void dispose() { 419 InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this); 420 InstanceManager.getDefault(CarRoads.class).removePropertyChangeListener(this); 421 if (_train != null) { 422 _train.removePropertyChangeListener(this); 423 } 424 super.dispose(); 425 } 426 427 @Override 428 public void propertyChange(java.beans.PropertyChangeEvent e) { 429 if (Control.SHOW_PROPERTY) { 430 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 431 .getNewValue()); 432 } 433 if (e.getPropertyName().equals(CarRoads.CARROADS_CHANGED_PROPERTY)) { 434 updateRoadComboBoxes(); 435 updateCarRoadNames(); 436 } 437 } 438 439 private final static Logger log = LoggerFactory.getLogger(TrainRoadOptionsFrame.class); 440}