001package jmri.jmrit.operations.locations.tools; 002 003import java.awt.*; 004import java.awt.event.ActionEvent; 005 006import javax.swing.*; 007 008import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 009import jmri.InstanceManager; 010import jmri.jmrit.operations.OperationsFrame; 011import jmri.jmrit.operations.OperationsXml; 012import jmri.jmrit.operations.locations.Location; 013import jmri.jmrit.operations.locations.Track; 014import jmri.jmrit.operations.rollingstock.cars.CarLoads; 015import jmri.jmrit.operations.rollingstock.cars.CarRoads; 016import jmri.jmrit.operations.setup.Control; 017import jmri.jmrit.operations.setup.Setup; 018import jmri.util.swing.JmriJOptionPane; 019 020/** 021 * Frame for user edit of track roads 022 * 023 * @author Dan Boudreau Copyright (C) 2013, 2014, 2026 024 */ 025public class TrackRoadEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 026 027 Location _location = null; 028 Track _track = null; 029 private static boolean roadAndLoadType = false; 030 031 // panels 032 JPanel pRoadControls = new JPanel(); 033 JPanel panelRoads = new JPanel(); 034 JScrollPane paneRoads = new JScrollPane(panelRoads); 035 036 // major buttons 037 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 038 JButton addRoadButton = new JButton(Bundle.getMessage("AddRoad")); 039 JButton deleteRoadButton = new JButton(Bundle.getMessage("DeleteRoad")); 040 JButton deleteAllRoadsButton = new JButton(Bundle.getMessage("DeleteAll")); 041 042 // radio buttons 043 JRadioButton roadNameAll = new JRadioButton(Bundle.getMessage("AcceptAll")); 044 JRadioButton roadNameInclude = new JRadioButton(Bundle.getMessage("AcceptOnly")); 045 JRadioButton roadNameExclude = new JRadioButton(Bundle.getMessage("Exclude")); 046 047 // combo box 048 JComboBox<String> comboBoxRoads = InstanceManager.getDefault(CarRoads.class).getComboBox(); 049 JComboBox<String> comboBoxLoadTypes = InstanceManager.getDefault(CarLoads.class).getLoadTypesComboBox(); 050 051 // check boxes 052 JCheckBox roadAndLoadTypeCheckBox = new JCheckBox(Bundle.getMessage("RoadAndLoadType")); 053 054 // labels 055 JLabel trackName = new JLabel(); 056 057 public static final String DISPOSE = "dispose"; // NOI18N 058 public static final int MAX_NAME_LENGTH = Control.max_len_string_track_name; 059 060 public TrackRoadEditFrame() { 061 super(Bundle.getMessage("TitleEditTrackRoads")); 062 } 063 064 public void initComponents(Location location, Track track) { 065 _location = location; 066 _track = track; 067 068 // property changes 069 // listen for car road name changes 070 InstanceManager.getDefault(CarRoads.class).addPropertyChangeListener(this); 071 072 // the following code sets the frame's initial state 073 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 074 075 // Set up the panels 076 // Layout the panel by rows 077 // row 1 078 JPanel p1 = new JPanel(); 079 p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 080 p1.setMaximumSize(new Dimension(2000, 250)); 081 082 // row 1a 083 JPanel pTrackName = new JPanel(); 084 pTrackName.setLayout(new GridBagLayout()); 085 pTrackName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Track"))); 086 addItem(pTrackName, trackName, 0, 0); 087 088 // row 1b 089 JPanel pLocationName = new JPanel(); 090 pLocationName.setLayout(new GridBagLayout()); 091 pLocationName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Location"))); 092 addItem(pLocationName, new JLabel(_location.getName()), 0, 0); 093 094 p1.add(pTrackName); 095 p1.add(pLocationName); 096 097 // row 3 098 JPanel p3 = new JPanel(); 099 p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS)); 100 JScrollPane pane3 = new JScrollPane(p3); 101 pane3.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("RoadsTrack"))); 102 pane3.setMaximumSize(new Dimension(2000, 400)); 103 104 JPanel pRoadRadioButtons = new JPanel(); 105 pRoadRadioButtons.setLayout(new FlowLayout()); 106 107 pRoadRadioButtons.add(roadNameAll); 108 pRoadRadioButtons.add(roadNameInclude); 109 pRoadRadioButtons.add(roadNameExclude); 110 pRoadRadioButtons.add(roadAndLoadTypeCheckBox); 111 112 pRoadControls.setLayout(new FlowLayout()); 113 114 pRoadControls.add(comboBoxRoads); 115 pRoadControls.add(comboBoxLoadTypes); 116 pRoadControls.add(addRoadButton); 117 pRoadControls.add(deleteRoadButton); 118 pRoadControls.add(deleteAllRoadsButton); 119 120 pRoadControls.setVisible(false); 121 comboBoxLoadTypes.setVisible(false); 122 roadAndLoadTypeCheckBox.setSelected(roadAndLoadType); 123 124 p3.add(pRoadRadioButtons); 125 p3.add(pRoadControls); 126 127 // row 4 128 panelRoads.setLayout(new GridBagLayout()); 129 paneRoads.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Roads"))); 130 131 ButtonGroup roadGroup = new ButtonGroup(); 132 roadGroup.add(roadNameAll); 133 roadGroup.add(roadNameInclude); 134 roadGroup.add(roadNameExclude); 135 136 // row 12 137 JPanel panelButtons = new JPanel(); 138 panelButtons.setLayout(new GridBagLayout()); 139 panelButtons.setBorder(BorderFactory.createTitledBorder("")); 140 panelButtons.setMaximumSize(new Dimension(2000, 200)); 141 142 // row 13 143 addItem(panelButtons, saveButton, 0, 0); 144 145 getContentPane().add(p1); 146 getContentPane().add(pane3); 147 getContentPane().add(paneRoads); 148 getContentPane().add(panelButtons); 149 150 // setup buttons 151 addButtonAction(saveButton); 152 153 addButtonAction(deleteRoadButton); 154 addButtonAction(deleteAllRoadsButton); 155 addButtonAction(addRoadButton); 156 157 addRadioButtonAction(roadNameAll); 158 addRadioButtonAction(roadNameInclude); 159 addRadioButtonAction(roadNameExclude); 160 161 addCheckBoxAction(roadAndLoadTypeCheckBox); 162 163 // road fields and enable buttons 164 if (_track != null) { 165 _track.addPropertyChangeListener(this); 166 trackName.setText(_track.getName()); 167 enableButtons(true); 168 } else { 169 enableButtons(false); 170 } 171 172 updateRoadComboBox(); 173 updateRoadNames(); 174 175 // add help menu to window 176 addHelpMenu("package.jmri.jmrit.operations.Operations_RoadOptions", true); // NOI18N 177 178 initMinimumSize(new Dimension(Control.panelWidth600, Control.panelHeight400)); 179 } 180 181 // Save, Delete, Add 182 @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "GUI ease of use") 183 @Override 184 public void buttonActionPerformed(ActionEvent ae) { 185 if (_track == null) { 186 return; 187 } 188 if (ae.getSource() == saveButton) { 189 log.debug("track save button activated"); 190 if (!checkForErrors()) { 191 roadAndLoadType = roadAndLoadTypeCheckBox.isSelected(); 192 OperationsXml.save(); 193 if (Setup.isCloseWindowOnSaveEnabled()) { 194 dispose(); 195 } 196 } 197 } 198 if (ae.getSource() == addRoadButton) { 199 String roadName = (String) comboBoxRoads.getSelectedItem(); 200 if (roadAndLoadTypeCheckBox.isSelected()) { 201 roadName = roadName + CarRoads.SPLIT_CHAR + comboBoxLoadTypes.getSelectedItem(); 202 } 203 _track.addRoadName(roadName); 204 selectNextItemComboBox(comboBoxRoads); 205 } 206 if (ae.getSource() == deleteRoadButton) { 207 String roadName = (String) comboBoxRoads.getSelectedItem(); 208 if (roadAndLoadTypeCheckBox.isSelected()) { 209 roadName = roadName + CarRoads.SPLIT_CHAR + comboBoxLoadTypes.getSelectedItem(); 210 } 211 _track.deleteRoadName(roadName); 212 selectNextItemComboBox(comboBoxRoads); 213 } 214 if (ae.getSource() == deleteAllRoadsButton) { 215 deleteAllRoads(); 216 } 217 } 218 219 protected void enableButtons(boolean enabled) { 220 saveButton.setEnabled(enabled); 221 roadNameAll.setEnabled(enabled); 222 roadNameInclude.setEnabled(enabled); 223 roadNameExclude.setEnabled(enabled); 224 } 225 226 @Override 227 public void radioButtonActionPerformed(ActionEvent ae) { 228 log.debug("radio button activated"); 229 if (ae.getSource() == roadNameAll) { 230 _track.setRoadOption(Track.ALL_ROADS); 231 } 232 if (ae.getSource() == roadNameInclude) { 233 _track.setRoadOption(Track.INCLUDE_ROADS); 234 } 235 if (ae.getSource() == roadNameExclude) { 236 _track.setRoadOption(Track.EXCLUDE_ROADS); 237 } 238 } 239 240 private void updateRoadComboBox() { 241 InstanceManager.getDefault(CarRoads.class).updateComboBox(comboBoxRoads); 242 } 243 244 private void updateRoadNames() { 245 log.debug("Update road names"); 246 panelRoads.removeAll(); 247 if (_track != null) { 248 // set radio button 249 roadNameAll.setSelected(_track.getRoadOption().equals(Track.ALL_ROADS)); 250 roadNameInclude.setSelected(_track.getRoadOption().equals(Track.INCLUDE_ROADS)); 251 roadNameExclude.setSelected(_track.getRoadOption().equals(Track.EXCLUDE_ROADS)); 252 253 pRoadControls.setVisible(!roadNameAll.isSelected()); 254 255 if (!roadNameAll.isSelected()) { 256 int x = 0; 257 int y = 0; // vertical position in panel 258 259 int numberOfRoads = getNumberOfCheckboxesPerLine(); 260 for (String roadName : _track.getRoadNames()) { 261 JLabel road = new JLabel(); 262 road.setText(roadName); 263 addItemTop(panelRoads, road, x++, y); 264 // limit the number of roads per line 265 if (x > numberOfRoads) { 266 y++; 267 x = 0; 268 } 269 } 270 revalidate(); 271 } 272 } else { 273 roadNameAll.setSelected(true); 274 } 275 panelRoads.repaint(); 276 panelRoads.revalidate(); 277 } 278 279 private void deleteAllRoads() { 280 if (_track != null) { 281 for (String roadName : _track.getRoadNames()) { 282 _track.deleteRoadName(roadName); 283 } 284 } 285 } 286 287 @Override 288 public void checkBoxActionPerformed(ActionEvent ae) { 289 JCheckBox b = (JCheckBox) ae.getSource(); 290 comboBoxLoadTypes.setVisible(b.isSelected()); 291 } 292 293 private boolean checkForErrors() { 294 if (_track.getRoadOption().equals(Track.INCLUDE_ROADS) && _track.getRoadNames().length == 0) { 295 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("ErrorNeedRoads"), 296 Bundle.getMessage("ErrorNoRoads"), 297 JmriJOptionPane.ERROR_MESSAGE); 298 return true; 299 } 300 return false; 301 } 302 303 @Override 304 public void dispose() { 305 if (_track != null) { 306 _track.removePropertyChangeListener(this); 307 } 308 InstanceManager.getDefault(CarRoads.class).removePropertyChangeListener(this); 309 super.dispose(); 310 } 311 312 @Override 313 public void propertyChange(java.beans.PropertyChangeEvent e) { 314 if (Control.SHOW_PROPERTY) { 315 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 316 .getNewValue()); 317 } 318 if (e.getPropertyName().equals(CarRoads.CARROADS_CHANGED_PROPERTY)) { 319 updateRoadComboBox(); 320 updateRoadNames(); 321 } 322 if (e.getPropertyName().equals(Track.ROADS_CHANGED_PROPERTY)) { 323 updateRoadNames(); 324 } 325 } 326 327 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrackRoadEditFrame.class); 328}