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