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}