001package jmri.jmrit.operations.locations.tools;
002
003import java.awt.Dimension;
004import java.awt.GridBagLayout;
005
006import javax.swing.*;
007
008import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
009import jmri.InstanceManager;
010import jmri.jmrit.operations.OperationsFrame;
011import jmri.jmrit.operations.OperationsXml;
012import jmri.jmrit.operations.locations.*;
013import jmri.jmrit.operations.rollingstock.RollingStock;
014import jmri.jmrit.operations.rollingstock.RollingStockManager;
015import jmri.jmrit.operations.rollingstock.cars.CarManager;
016import jmri.jmrit.operations.rollingstock.engines.EngineManager;
017import jmri.jmrit.operations.setup.Control;
018import jmri.jmrit.operations.setup.Setup;
019import jmri.jmrit.operations.trains.TrainCommon;
020import jmri.util.swing.JmriJOptionPane;
021
022/**
023 * Frame for copying a location for operations.
024 *
025 * @author Bob Jacobsen Copyright (C) 2001
026 * @author Daniel Boudreau Copyright (C) 2014
027 */
028public class LocationCopyFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
029
030    LocationManager locationManager = InstanceManager.getDefault(LocationManager.class);
031
032    // text field
033    JTextField loctionNameTextField = new javax.swing.JTextField(Control.max_len_string_location_name);
034
035    // major buttons
036    JButton copyButton = new javax.swing.JButton(Bundle.getMessage("ButtonCopy"));
037    JButton saveButton = new javax.swing.JButton(Bundle.getMessage("ButtonSave"));
038
039    // combo boxes
040    JComboBox<Location> locationBox = locationManager.getComboBox();
041
042    // checkboxes
043    JCheckBox moveRollingStockCheckBox = new JCheckBox(Bundle.getMessage("MoveRollingStock"));
044    JCheckBox deleteTrackCheckBox = new JCheckBox(Bundle.getMessage("DeleteCopiedTrack"));
045
046    // remember state of checkboxes during a session
047    static boolean moveRollingStock = false;
048    static boolean deleteTrack = false;
049    
050    Location _location;
051    
052    public LocationCopyFrame(Location location) {
053        super(Bundle.getMessage("MenuItemCopyLocation"));
054        _location = location;
055        initComponents();
056    }
057
058    @Override
059    public void initComponents() {
060
061        // general GUI config
062        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
063
064        // Set up the panels
065        // Layout the panel by rows
066        // row 1
067        JPanel pName = new JPanel();
068        pName.setLayout(new GridBagLayout());
069        pName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LocationName")));
070        addItem(pName, loctionNameTextField, 0, 0);
071
072        // row 2
073        JPanel pCopy = new JPanel();
074        pCopy.setLayout(new GridBagLayout());
075        pCopy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SelectLocationToCopy")));
076        addItem(pCopy, locationBox, 0, 0);
077
078        // row 3
079        JPanel pOptions = new JPanel();
080        pOptions.setLayout(new GridBagLayout());
081        pOptions.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Options")));
082        addItemLeft(pOptions, moveRollingStockCheckBox, 0, 1);
083        addItemLeft(pOptions, deleteTrackCheckBox, 0, 2);
084
085        // row 4
086        JPanel pButton = new JPanel();
087        pButton.setLayout(new GridBagLayout());
088        addItem(pButton, copyButton, 0, 0);
089        addItem(pButton, saveButton, 1, 0);
090
091        getContentPane().add(pName);
092        getContentPane().add(pCopy);
093        getContentPane().add(pOptions);
094        getContentPane().add(pButton);
095
096        // set the checkbox states
097        moveRollingStockCheckBox.setSelected(moveRollingStock);
098        deleteTrackCheckBox.setSelected(deleteTrack);
099        deleteTrackCheckBox.setEnabled(moveRollingStockCheckBox.isSelected());
100
101        // get notified if combo box gets modified
102        locationManager.addPropertyChangeListener(this);
103
104        // add help menu to window
105        addHelpMenu("package.jmri.jmrit.operations.Operations_CopyLocation", true); // NOI18N
106
107        initMinimumSize(new Dimension(Control.panelWidth400, Control.panelHeight400));
108
109        // setup buttons
110        addButtonAction(copyButton);
111        addButtonAction(saveButton);
112
113        addCheckBoxAction(moveRollingStockCheckBox);
114        
115        locationBox.setSelectedItem(_location);
116    }
117
118    @Override
119    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "GUI ease of use")
120    protected void buttonActionPerformed(java.awt.event.ActionEvent ae) {
121        if (ae.getSource() == copyButton) {
122            log.debug("copy location button activated");
123            if (!checkName()) {
124                return;
125            }
126
127            if (locationBox.getSelectedItem() == null) {
128                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("SelectLocationToCopy"), Bundle
129                        .getMessage("CanNotLocation", Bundle.getMessage("ButtonCopy")), JmriJOptionPane.ERROR_MESSAGE);
130                return;
131            }
132
133            Location location = (Location) locationBox.getSelectedItem();
134            // check to see if there are cars scheduled for pickup or set out
135            if (moveRollingStockCheckBox.isSelected()) {
136                for (Track track : location.getTracksList()) {
137                    if (track.getPickupRS() > 0) {
138                        JmriJOptionPane.showMessageDialog(this,
139                                Bundle.getMessage("FoundRollingStockPickUp", track.getPickupRS()),
140                                Bundle.getMessage("TrainsServicingTrack", track.getName()),
141                                JmriJOptionPane.WARNING_MESSAGE);
142                        return; // can't move rolling stock, some are scheduled for a pick up
143                    }
144                    if (track.getDropRS() > 0) {
145                        JmriJOptionPane.showMessageDialog(this,
146                                Bundle.getMessage("FoundRollingStockDrop", track.getDropRS()),
147                                Bundle.getMessage("TrainsServicingTrack", track.getName()),
148                                JmriJOptionPane.WARNING_MESSAGE);
149                        return; // can't move rolling stock, some are scheduled for drops
150                    }
151                }
152            }
153            // now copy all of the tracks
154            Location newLocation = locationManager.newLocation(loctionNameTextField.getText());
155            location.copyLocation(newLocation);
156
157            // does the user want the cars to also move to the new tracks?
158            if (moveRollingStockCheckBox.isSelected()) {
159                for (Track track : location.getTracksList()) {
160                    moveRollingStock(track, newLocation.getTrackByName(track.getName(), null));
161                    if (deleteTrackCheckBox.isSelected()) {
162                        location.deleteTrack(track);
163                    }
164                }
165            }
166        }
167        if (ae.getSource() == saveButton) {
168            log.debug("save track button activated");
169            // save checkbox states
170            moveRollingStock = moveRollingStockCheckBox.isSelected();
171            deleteTrack = deleteTrackCheckBox.isSelected();
172            // save location file
173            OperationsXml.save();
174            if (Setup.isCloseWindowOnSaveEnabled()) {
175                dispose();
176            }
177        }
178    }
179
180    @Override
181    protected void checkBoxActionPerformed(java.awt.event.ActionEvent ae) {
182        if (ae.getSource() == moveRollingStockCheckBox) {
183            deleteTrackCheckBox.setEnabled(moveRollingStockCheckBox.isSelected());
184            deleteTrackCheckBox.setSelected(false);
185        }
186    }
187
188    protected void updateComboBoxes() {
189        log.debug("update location combobox");
190        Object item = locationBox.getSelectedItem(); // remember which object was selected
191        locationManager.updateComboBox(locationBox);
192        locationBox.setSelectedItem(item);
193    }
194
195    /**
196     *
197     * @return true if name entered OK and isn't too long
198     */
199    protected boolean checkName() {
200        if (loctionNameTextField.getText().trim().isEmpty()) {
201            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("MustEnterName"),
202                    Bundle.getMessage("CanNotLocation", Bundle.getMessage("ButtonCopy")),
203                    JmriJOptionPane.ERROR_MESSAGE);
204            return false;
205        }
206        if (TrainCommon.splitString(loctionNameTextField.getText()).length() > Control.max_len_string_location_name) {
207            JmriJOptionPane.showMessageDialog(this,
208                    Bundle.getMessage("LocationNameLengthMax",
209                            Integer.toString(Control.max_len_string_location_name + 1)),
210                    Bundle.getMessage("CanNotLocation", Bundle.getMessage("ButtonCopy")),
211                    JmriJOptionPane.ERROR_MESSAGE);
212            return false;
213        }
214        Location check = locationManager.getLocationByName(loctionNameTextField.getText());
215        if (check != null) {
216            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("LocationAlreadyExists"),
217                    Bundle.getMessage("CanNotLocation", Bundle.getMessage("ButtonCopy")),
218                    JmriJOptionPane.ERROR_MESSAGE);
219            return false;
220        }
221        return true;
222    }
223
224    protected void moveRollingStock(Track fromTrack, Track toTrack) {
225        moveRollingStock(fromTrack, toTrack, InstanceManager.getDefault(CarManager.class));
226        moveRollingStock(fromTrack, toTrack, InstanceManager.getDefault(EngineManager.class));
227    }
228
229    private void moveRollingStock(Track fromTrack, Track toTrack, RollingStockManager<? extends RollingStock> manager) {
230        for (RollingStock rs : manager.getByIdList()) {
231            if (rs.getTrack() == fromTrack) {
232                rs.setLocation(toTrack.getLocation(), toTrack, RollingStock.FORCE);
233            }
234        }
235    }
236
237    @Override
238    public void dispose() {
239        locationManager.removePropertyChangeListener(this);
240        super.dispose();
241    }
242
243    @Override
244    public void propertyChange(java.beans.PropertyChangeEvent e) {
245        log.debug("PropertyChange ({}) new: ({})", e.getPropertyName(), e.getNewValue());
246        if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY)) {
247            updateComboBoxes();
248        }
249    }
250
251    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LocationCopyFrame.class);
252}