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