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