001package jmri.jmrit.operations.locations.tools; 002 003import java.awt.*; 004import java.util.List; 005 006import javax.swing.*; 007 008import jmri.jmrit.operations.OperationsFrame; 009import jmri.jmrit.operations.OperationsXml; 010import jmri.jmrit.operations.locations.*; 011import jmri.jmrit.operations.setup.Control; 012import jmri.jmrit.operations.setup.Setup; 013import jmri.util.swing.JmriJOptionPane; 014 015/** 016 * 017 * Things to test with this frame: 018 * 019 * - Adding a new Pool name to the available pools list 020 * 021 * - What happens when a null track is passed to the frame 022 * 023 * - Selecting an existing pool and saving it to the track 024 * 025 * - Selecting a minimum length and saving it to the track 026 * 027 * - Not sure if we want to test the status display panel, as it doesn't do 028 * anything. 029 * 030 * @author Daniel Boudreau Copyright (C) 2011 031 * @author Gregory Madsen Copyright (C) 2012 032 * 033 * 034 */ 035class PoolTrackFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 036 037 // labels 038 JLabel name = new JLabel(Bundle.getMessage("Name")); 039 JLabel minimum = new JLabel(Bundle.getMessage("Minimum")); 040 JLabel maximum = new JLabel(Bundle.getMessage("Maximum")); 041 JLabel length = new JLabel(Bundle.getMessage("Length")); 042 043 // text field 044 JTextField trackPoolNameTextField = new JTextField(20); 045 JTextField trackMinLengthTextField = new JTextField(5); 046 047 // combo box 048 JComboBox<Pool> comboBoxPools = new JComboBox<>(); 049 050 // train departure order out of staging 051 JRadioButton orderNormal = new JRadioButton(Bundle.getMessage("Normal")); 052 JRadioButton orderFIFO = new JRadioButton(Bundle.getMessage("DescriptiveFIFO")); 053 JRadioButton orderLIFO = new JRadioButton(Bundle.getMessage("DescriptiveLIFO")); 054 055 // major buttons 056 JButton addButton = new JButton(Bundle.getMessage("Add")); 057 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 058 059 // pool status 060 JPanel poolStatus = new JPanel(); 061 062 private TrackEditFrame _tefx; 063 protected Track _track; 064 protected Pool _pool; 065 066 public PoolTrackFrame(TrackEditFrame tef) { 067 super(); 068 069 _tefx = tef; 070 _track = _tefx._track; 071 } 072 073 public PoolTrackFrame(Track track) { 074 super(); 075 _track = track; 076 } 077 078 @Override 079 public void initComponents() { 080 if (_track == null) { 081 log.debug("track is null, pools can not be created"); 082 return; 083 } 084 // the following code sets the frame's initial state 085 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 086 087 _track.addPropertyChangeListener(this); 088 _track.getLocation().addPropertyChangeListener(this); 089 090 _pool = _track.getPool(); 091 092 if (_pool != null) { 093 _pool.addPropertyChangeListener(this); 094 } 095 096 // load the panel 097 JPanel p1 = new JPanel(); 098 p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); 099 JScrollPane p1Pane = new JScrollPane(p1); 100 p1Pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 101 p1Pane.setBorder(BorderFactory.createTitledBorder("")); 102 103 // row 1 104 JPanel pt = new JPanel(); 105 pt.setLayout(new BoxLayout(pt, BoxLayout.X_AXIS)); 106 pt.setMaximumSize(new Dimension(2000, 250)); 107 108 // row 1a 109 JPanel pTrackName = new JPanel(); 110 pTrackName.setLayout(new GridBagLayout()); 111 pTrackName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Track"))); 112 addItem(pTrackName, new JLabel(_track.getName()), 0, 0); 113 114 // row 1b 115 JPanel pLocationName = new JPanel(); 116 pLocationName.setLayout(new GridBagLayout()); 117 pLocationName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Location"))); 118 addItem(pLocationName, new JLabel(_track.getLocation().getName()), 0, 0); 119 120 pt.add(pTrackName); 121 pt.add(pLocationName); 122 123 JPanel poolName = new JPanel(); 124 poolName.setLayout(new GridBagLayout()); 125 poolName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PoolName"))); 126 addItem(poolName, trackPoolNameTextField, 0, 0); 127 addItem(poolName, addButton, 1, 0); 128 129 JPanel selectPool = new JPanel(); 130 selectPool.setLayout(new GridBagLayout()); 131 selectPool.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PoolSelect"))); 132 addItem(selectPool, comboBoxPools, 0, 0); 133 134 JPanel minLengthTrack = new JPanel(); 135 minLengthTrack.setLayout(new GridBagLayout()); 136 minLengthTrack 137 .setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PoolTrackMinimum", _track.getName()))); 138 addItem(minLengthTrack, trackMinLengthTextField, 0, 0); 139 140 trackMinLengthTextField.setText(Integer.toString(_track.getMinimumLength())); 141 142 // row 4, train service order panel 143 JPanel panelOrder = new JPanel(); 144 panelOrder.setLayout(new GridBagLayout()); 145 panelOrder.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainPickupOrder"))); 146 panelOrder.add(orderNormal); 147 panelOrder.add(orderFIFO); 148 panelOrder.add(orderLIFO); 149 150 ButtonGroup orderGroup = new ButtonGroup(); 151 orderGroup.add(orderNormal); 152 orderGroup.add(orderFIFO); 153 orderGroup.add(orderLIFO); 154 155 updateRadioButtons(); 156 157 addRadioButtonAction(orderNormal); 158 addRadioButtonAction(orderFIFO); 159 addRadioButtonAction(orderLIFO); 160 161 JPanel savePool = new JPanel(); 162 savePool.setLayout(new GridBagLayout()); 163 savePool.setBorder(BorderFactory.createTitledBorder("")); 164 addItem(savePool, saveButton, 0, 0); 165 166 p1.add(pt); 167 p1.add(poolName); 168 p1.add(selectPool); 169 p1.add(minLengthTrack); 170 if (_track.isStaging()) { 171 p1.add(panelOrder); 172 } 173 p1.add(savePool); 174 175 JPanel p2 = new JPanel(); 176 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS)); 177 JScrollPane p2Pane = new JScrollPane(p2); 178 p2Pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 179 p2Pane.setBorder(BorderFactory.createTitledBorder("")); 180 181 // pool status panel 182 poolStatus.setLayout(new GridBagLayout()); 183 184 p2.add(poolStatus); 185 186 getContentPane().add(p1Pane); 187 getContentPane().add(p2Pane); 188 setTitle(Bundle.getMessage("MenuItemPoolTrack")); 189 190 // load comboBox 191 updatePoolsComboBox(); 192 updatePoolStatus(); 193 194 // button action - These use a convention in the OperationsFrame base 195 // class that requires the events to be sorted out in 196 // buttonActionPerformed. 197 addButtonAction(addButton); 198 addButtonAction(saveButton); 199 200 // add help menu to window 201 addHelpMenu("package.jmri.jmrit.operations.Operations_Pools", true); // NOI18N 202 203 initMinimumSize(new Dimension(Control.panelWidth600, Control.panelHeight300)); 204 } 205 206 private void updatePoolsComboBox() { 207 _track.getLocation().updatePoolComboBox(comboBoxPools); 208 comboBoxPools.setSelectedItem(_track.getPool()); 209 } 210 211 private void updatePoolStatus() { 212 // This shows the details of the current member tracks in the Pool. 213 poolStatus.removeAll(); 214 215 addItemLeft(poolStatus, name, 0, 0); 216 addItem(poolStatus, maximum, 1, 0); 217 addItem(poolStatus, minimum, 2, 0); 218 addItem(poolStatus, length, 3, 0); 219 220 String poolName = ""; 221 if (_track.getPool() != null) { 222 Pool pool = _track.getPool(); 223 poolName = pool.getName(); 224 List<Track> tracks = pool.getTracks(); 225 int totalMinLength = 0; 226 int totalLength = 0; 227 for (int i = 0; i < tracks.size(); i++) { 228 Track track = tracks.get(i); 229 JLabel name = new JLabel(); 230 name.setText(track.getName()); 231 232 JLabel maximum = new JLabel(); 233 maximum.setText(Integer.toString(pool.getMaxLengthTrack(track))); 234 235 JLabel minimum = new JLabel(); 236 minimum.setText(Integer.toString(track.getMinimumLength())); 237 totalMinLength = totalMinLength + track.getMinimumLength(); 238 239 JLabel length = new JLabel(); 240 length.setText(Integer.toString(track.getLength())); 241 totalLength = totalLength + track.getLength(); 242 243 addItemLeft(poolStatus, name, 0, i + 1); 244 addItem(poolStatus, maximum, 1, i + 1); 245 addItem(poolStatus, minimum, 2, i + 1); 246 addItem(poolStatus, length, 3, i + 1); 247 } 248 // Summary 249 int totalLine = tracks.size() + 1; 250 JLabel total = new JLabel(Bundle.getMessage("Totals")); 251 addItem(poolStatus, total, 0, totalLine); 252 if (totalMinLength > totalLength) { 253 JLabel error = new JLabel(Bundle.getMessage("ErrorMinLen")); 254 error.setForeground(Color.RED); 255 addItem(poolStatus, error, 1, totalLine); 256 } 257 JLabel totalMin = new JLabel(); 258 totalMin.setText(Integer.toString(totalMinLength)); 259 addItem(poolStatus, totalMin, 2, totalLine); 260 JLabel totalLen = new JLabel(); 261 totalLen.setText(Integer.toString(totalLength)); 262 addItem(poolStatus, totalLen, 3, totalLine); 263 } 264 poolStatus.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PoolTracks", poolName))); 265 poolStatus.repaint(); 266 poolStatus.revalidate(); 267 setPreferredSize(null); // kill JMRI window size 268 pack(); 269 } 270 271 @Override 272 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 273 if (ae.getSource() == addButton) { 274 Location location = _track.getLocation(); 275 location.addPool(trackPoolNameTextField.getText().trim()); 276 } 277 278 if (ae.getSource() == saveButton) { 279 try { 280 _track.setMinimumLength(Integer.parseInt(trackMinLengthTextField.getText())); 281 } catch (NumberFormatException e) { 282 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("TrackMustBeNumber"), Bundle 283 .getMessage("ErrorTrackLength"), JmriJOptionPane.ERROR_MESSAGE); 284 return; 285 } 286 287 if (_pool != null) { 288 _pool.removePropertyChangeListener(this); 289 } 290 _pool = (Pool) comboBoxPools.getSelectedItem(); 291 if (_pool != null) { 292 _pool.addPropertyChangeListener(this); 293 } 294 _track.setPool(_pool); // this causes a property change to this frame 295 updateServiceOrder(); 296 297 // save location file 298 OperationsXml.save(); 299 if (Setup.isCloseWindowOnSaveEnabled()) { 300 dispose(); 301 } 302 } 303 } 304 305 @Override 306 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 307 log.debug("radio button activated"); 308 if (_track.getPool() != null) { 309 for (Track track : _track.getPool().getTracks()) { 310 if (ae.getSource() == orderNormal) { 311 track.setServiceOrder(Track.NORMAL); 312 } 313 if (ae.getSource() == orderFIFO) { 314 track.setServiceOrder(Track.FIFO); 315 } 316 if (ae.getSource() == orderLIFO) { 317 track.setServiceOrder(Track.LIFO); 318 } 319 } 320 } 321 } 322 323 private void updateServiceOrder() { 324 if (_track.isStaging() && _track.getPool() != null) { 325 for (Track track : _track.getPool().getTracks()) { 326 if (track != _track) { 327 _track.setServiceOrder(track.getServiceOrder()); 328 updateRadioButtons(); 329 break; 330 } 331 } 332 } 333 } 334 335 private void updateRadioButtons() { 336 orderNormal.setSelected(_track.getServiceOrder().equals(Track.NORMAL)); 337 orderFIFO.setSelected(_track.getServiceOrder().equals(Track.FIFO)); 338 orderLIFO.setSelected(_track.getServiceOrder().equals(Track.LIFO)); 339 } 340 341 @Override 342 public void dispose() { 343 if (_track != null) { 344 _track.removePropertyChangeListener(this); 345 _track.getLocation().removePropertyChangeListener(this); 346 } 347 if (_pool != null) { 348 _pool.removePropertyChangeListener(this); 349 } 350 super.dispose(); 351 } 352 353 @Override 354 public void propertyChange(java.beans.PropertyChangeEvent e) { 355 // This should move to the base class 356 // Just call LogEvent(e); instead. It will figure out if logging is 357 // enabled, etc. 358 if (Control.SHOW_PROPERTY) { 359 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 360 .getNewValue()); 361 } 362 if (e.getPropertyName().equals(Location.POOL_LENGTH_CHANGED_PROPERTY)) { 363 updatePoolsComboBox(); 364 } 365 366 if (e.getPropertyName().equals(Pool.LISTCHANGE_CHANGED_PROPERTY) 367 || e.getPropertyName().equals(Location.LENGTH_CHANGED_PROPERTY) 368 || e.getPropertyName().equals(Track.POOL_CHANGED_PROPERTY) 369 || e.getPropertyName().equals(Track.MIN_LENGTH_CHANGED_PROPERTY)) { 370 updatePoolStatus(); 371 } 372 } 373 374 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PoolTrackFrame.class); 375}