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