001package jmri.jmrit.operations.rollingstock.cars.tools;
002
003import java.awt.Dimension;
004import java.awt.GridBagLayout;
005
006import javax.swing.*;
007
008import jmri.InstanceManager;
009import jmri.jmrit.operations.OperationsFrame;
010import jmri.jmrit.operations.OperationsXml;
011import jmri.jmrit.operations.locations.LocationManager;
012import jmri.jmrit.operations.locations.schedules.ScheduleManager;
013import jmri.jmrit.operations.rollingstock.cars.*;
014import jmri.jmrit.operations.setup.Control;
015import jmri.jmrit.operations.setup.Setup;
016import jmri.jmrit.operations.trains.TrainManager;
017import jmri.util.swing.JmriJOptionPane;
018
019/**
020 * Frame for adding and editing the car load attribute for operations.
021 *
022 * @author Daniel Boudreau Copyright (C) 2009, 2010, 2011, 2023
023 */
024public class CarLoadEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
025
026    CarLoads carLoads = InstanceManager.getDefault(CarLoads.class);
027    CarTypes carTypes = InstanceManager.getDefault(CarTypes.class);
028
029    // labels
030    JLabel textSep = new JLabel();
031    JLabel quanity = new JLabel("0");
032
033    // major buttons
034    JButton addButton = new JButton(Bundle.getMessage("Add"));
035    JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete"));
036    JButton replaceButton = new JButton(Bundle.getMessage("Replace"));
037    JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
038
039    // combo boxes
040    JComboBox<String> typeComboBox = carTypes.getComboBox();
041    JComboBox<String> loadComboBox;
042    JComboBox<String> priorityComboBox = carLoads.getPriorityComboBox();
043    JComboBox<String> hazardousComboBox = carLoads.getHazardousComboBox();
044    JComboBox<String> loadTypeComboBox = carLoads.getLoadTypesComboBox();
045    
046    // check boxes
047    JCheckBox allTypesCheckBox = new JCheckBox(Bundle.getMessage("All"));
048    
049    // text boxes
050    JTextField addTextBox = new JTextField(10);
051    JTextField pickupCommentTextField = new JTextField(35);
052    JTextField dropCommentTextField = new JTextField(35);
053
054    public CarLoadEditFrame() {
055        super(Bundle.getMessage("TitleCarEditLoad"));
056    }
057
058    String _type; // car type name
059    boolean menuActive = false;
060
061    public void initComponents(String type, String selectedItem) {
062
063        getContentPane().removeAll();
064
065        _type = type;
066        typeComboBox.setSelectedItem(_type);
067
068        loadComboBox = carLoads.getComboBox(_type);
069        carLoads.addPropertyChangeListener(this);
070        loadComboBox.setSelectedItem(selectedItem);
071        updateLoadType();
072        updatePriority();
073        updateHazardous();
074
075        // general GUI config
076        quanity.setVisible(showQuanity);
077
078        // car type panel
079        JPanel pType = new JPanel();
080        pType.setLayout(new GridBagLayout());
081        pType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type")));
082        addItem(pType, typeComboBox, 0, 0);
083        addItem(pType, allTypesCheckBox, 1, 0);
084        
085        allTypesCheckBox.setToolTipText(Bundle.getMessage("TipCarLoadAll"));
086
087        // load panel
088        JPanel pLoad = new JPanel();
089        pLoad.setLayout(new GridBagLayout());
090        pLoad.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Load")));
091
092        // row 2
093        addItem(pLoad, addTextBox, 2, 2);
094        addItem(pLoad, addButton, 3, 2);
095
096        // row 3
097        addItem(pLoad, quanity, 1, 3);
098        addItem(pLoad, loadComboBox, 2, 3);
099        addItem(pLoad, deleteButton, 3, 3);
100
101        // row 4
102        addItem(pLoad, replaceButton, 3, 4);
103
104        deleteButton.setToolTipText(Bundle.getMessage("TipDeleteAttributeName",
105                Bundle.getMessage("Load")));
106        addButton.setToolTipText(Bundle.getMessage("TipAddAttributeName",
107                Bundle.getMessage("Load")));
108        replaceButton.setToolTipText(Bundle.getMessage("TipReplaceAttributeName",
109                Bundle.getMessage("Load")));
110
111        // row 6
112        JPanel pLoadType = new JPanel();
113        pLoadType.setLayout(new BoxLayout(pLoadType, BoxLayout.Y_AXIS));
114        pLoadType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLoadType")));
115        addItem(pLoadType, loadTypeComboBox, 0, 0);
116
117        // row 8
118        JPanel pPriority = new JPanel();
119        pPriority.setLayout(new BoxLayout(pPriority, BoxLayout.Y_AXIS));
120        pPriority.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPriority")));
121        addItem(pPriority, priorityComboBox, 0, 0);
122
123        // row 9
124        JPanel pHazardous = new JPanel();
125        pHazardous.setLayout(new BoxLayout(pHazardous, BoxLayout.Y_AXIS));
126        pHazardous.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Hazardous")));
127        addItem(pHazardous, hazardousComboBox, 0, 0);
128
129        // row 10
130        // optional panel
131        JPanel pOptionalPickup = new JPanel();
132        pOptionalPickup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptionalPickup")));
133        addItem(pOptionalPickup, pickupCommentTextField, 0, 0);
134
135        // row 12
136        JPanel pOptionalDrop = new JPanel();
137        pOptionalDrop.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOptionalDrop")));
138        addItem(pOptionalDrop, dropCommentTextField, 0, 0);
139
140        // row 14
141        JPanel pControl = new JPanel();
142        pControl.setLayout(new BoxLayout(pControl, BoxLayout.Y_AXIS));
143        addItem(pControl, saveButton, 0, 0);
144
145        // add panels
146        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
147        getContentPane().add(pType);
148        getContentPane().add(pLoad);
149        getContentPane().add(pLoadType);
150        getContentPane().add(pPriority);
151        getContentPane().add(pHazardous);
152        getContentPane().add(pOptionalPickup);
153        getContentPane().add(pOptionalDrop);
154        getContentPane().add(pControl);
155
156        addButtonAction(addButton);
157        addButtonAction(deleteButton);
158        addButtonAction(replaceButton);
159        addButtonAction(saveButton);
160
161        addComboBoxAction(typeComboBox);
162        addComboBoxAction(loadComboBox);
163        
164        addCheckBoxAction(allTypesCheckBox);
165
166        updateCarCommentFields();
167
168        enableButtons();
169
170        // build menu
171        JMenuBar menuBar = new JMenuBar();
172        JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
173        toolMenu.add(new CarLoadAttributeAction(this));
174        toolMenu.add(new PrintCarLoadsAction(true));
175        toolMenu.add(new PrintCarLoadsAction(false));
176        menuBar.add(toolMenu);
177        setJMenuBar(menuBar);
178        // add help menu to window
179        addHelpMenu("package.jmri.jmrit.operations.Operations_EditCarLoads", true); // NOI18N
180
181        initMinimumSize(new Dimension(Control.panelWidth400, Control.panelHeight500));
182    }
183
184    // add, delete, replace, and save buttons
185    @Override
186    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
187        String loadName = addTextBox.getText().trim();
188        if (ae.getSource() == addButton || ae.getSource() == replaceButton) {
189            if (loadName.equals(NONE)) {
190                return;
191            }
192            if (loadName.length() > Control.max_len_string_attibute) {
193                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carAttribute",
194                        Control.max_len_string_attibute), Bundle.getMessage("canNotUseLoadName"),
195                        JmriJOptionPane.ERROR_MESSAGE);
196                return;
197            }
198            // can't have the " & " as part of the load name
199            if (loadName.contains(CarLoad.SPLIT_CHAR)) {
200                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carNameNoAndChar",
201                        CarLoad.SPLIT_CHAR), Bundle.getMessage("canNotUseLoadName"),
202                        JmriJOptionPane.ERROR_MESSAGE);
203                return;
204            }
205        }
206        if (ae.getSource() == addButton) {
207            addLoadName(loadName);
208        }
209        if (ae.getSource() == deleteButton) {
210            deleteLoadName();
211        }
212        if (ae.getSource() == replaceButton) {
213            replaceLoadName(loadName);
214        }
215        if (ae.getSource() == saveButton) {
216            saveLoadName();
217            OperationsXml.save(); // save all files that have been modified;
218            if (Setup.isCloseWindowOnSaveEnabled()) {
219                dispose();
220            }
221        }
222    }
223
224    @Override
225    protected void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
226        log.debug("Combo box action");
227        if (ae.getSource() == typeComboBox) {
228            _type = (String) typeComboBox.getSelectedItem();
229            updateLoadComboBox();
230            enableButtons();
231        }
232        updateCarQuanity();
233        updateLoadType();
234        updatePriority();
235        updateHazardous();
236        updateCarCommentFields();
237    }
238    
239    @Override
240    protected void checkBoxActionPerformed(java.awt.event.ActionEvent ae) {
241        typeComboBox.setEnabled(!allTypesCheckBox.isSelected());
242    }
243    
244    private void addLoadName(String loadName) {
245        if (allTypesCheckBox.isSelected()) {
246            for (String type : carTypes.getNames()) {
247                carLoads.addName(type, loadName);
248            }
249        } else {
250            carLoads.addName(_type, loadName);
251        }
252    }
253    
254    private void deleteLoadName() {
255        String deleteLoad = (String) loadComboBox.getSelectedItem();
256        if (deleteLoad.equals(carLoads.getDefaultEmptyName()) || deleteLoad.equals(carLoads.getDefaultLoadName())) {
257            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carLoadDefault"), Bundle
258                    .getMessage("canNotDelete", Bundle.getMessage("Load")),
259                    JmriJOptionPane.ERROR_MESSAGE);
260            return;
261        }
262        if (allTypesCheckBox.isSelected()) {
263            for (String type : carTypes.getNames()) {
264                replaceLoad(type, deleteLoad, null);
265                carLoads.deleteName(type, deleteLoad);
266            }
267        } else {
268            replaceLoad(_type, deleteLoad, null);
269            carLoads.deleteName(_type, deleteLoad);
270        }
271    }
272    
273    private void replaceLoadName(String loadName) {
274        String oldLoadName = (String) loadComboBox.getSelectedItem();
275        if (oldLoadName.equals(carLoads.getDefaultEmptyName())) {
276            if (JmriJOptionPane.showConfirmDialog(this,
277                    Bundle.getMessage("replaceDefaultEmpty",
278                            oldLoadName, loadName),
279                    Bundle.getMessage("replaceAll"),
280                    JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) {
281                return;
282            }
283            // don't allow the default names for load and empty to be the
284            // same
285            if (loadName.equals(carLoads.getDefaultEmptyName()) || loadName.equals(carLoads.getDefaultLoadName())) {
286                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carDefault"), Bundle
287                        .getMessage("canNotReplace", Bundle.getMessage("Load")),
288                        JmriJOptionPane.ERROR_MESSAGE);
289                return;
290            }
291            carLoads.setDefaultEmptyName(loadName);
292            replaceAllLoads(oldLoadName, loadName);
293            return;
294        }
295        if (oldLoadName.equals(carLoads.getDefaultLoadName())) {
296            if (JmriJOptionPane.showConfirmDialog(this,
297                    Bundle.getMessage("replaceDefaultLoad",
298                            oldLoadName, loadName),
299                    Bundle.getMessage("replaceAll"),
300                    JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) {
301                return;
302            }
303            // don't allow the default names for load and empty to be the
304            // same
305            if (loadName.equals(carLoads.getDefaultEmptyName()) || loadName.equals(carLoads.getDefaultLoadName())) {
306                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carDefault"), Bundle
307                        .getMessage("canNotReplace", Bundle.getMessage("Load")),
308                        JmriJOptionPane.ERROR_MESSAGE);
309                return;
310            }
311            carLoads.setDefaultLoadName(loadName);
312            replaceAllLoads(oldLoadName, loadName);
313            return;
314        }
315        if (JmriJOptionPane.showConfirmDialog(this,
316                Bundle.getMessage("replaceMsg",
317                        oldLoadName, loadName),
318                Bundle.getMessage("replaceAll"),
319                JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) {
320            return;
321        }
322        if (oldLoadName.equals(loadName)) {
323            return; // do nothing
324        }
325        // ComboBoxes get deselected during the addName operation
326        String loadType = carLoads.getLoadType(_type, oldLoadName);
327        String loadPriority = carLoads.getPriority(_type, oldLoadName);
328        boolean isHazardous = carLoads.isHazardous(_type, oldLoadName);
329        String pickupComment = carLoads.getPickupComment(_type, oldLoadName);
330        String dropComment = carLoads.getDropComment(_type, oldLoadName);
331        
332        if (allTypesCheckBox.isSelected()) {
333            for (String type : carTypes.getNames()) {
334                carLoads.addName(type, loadName);
335                carLoads.setLoadType(type, loadName, loadType);
336                carLoads.setPriority(type, loadName, loadPriority);
337                carLoads.setHazardous(type, loadName, isHazardous);
338                carLoads.setPickupComment(type, loadName, pickupComment);
339                carLoads.setDropComment(type, loadName, dropComment);
340                replaceLoad(type, oldLoadName, loadName);
341                carLoads.deleteName(type, oldLoadName);
342            }
343        } else {
344            carLoads.addName(_type, loadName);
345            carLoads.setLoadType(_type, loadName, loadType);
346            carLoads.setPriority(_type, loadName, loadPriority);
347            carLoads.setHazardous(_type, loadName, isHazardous);
348            carLoads.setPickupComment(_type, loadName, pickupComment);
349            carLoads.setDropComment(_type, loadName, dropComment);
350            replaceLoad(_type, oldLoadName, loadName);
351            carLoads.deleteName(_type, oldLoadName);
352        }
353    }
354    
355    private void saveLoadName() {
356        if (allTypesCheckBox.isSelected()) {
357            for (String type : carTypes.getNames()) {
358                saveLoadName(type);
359            }
360        } else {
361            saveLoadName(_type);
362        }
363    }
364        
365    private void saveLoadName(String type) {
366        carLoads.setLoadType(type, (String) loadComboBox.getSelectedItem(), (String) loadTypeComboBox
367                .getSelectedItem());
368        carLoads.setPriority(type, (String) loadComboBox.getSelectedItem(),
369                (String) priorityComboBox.getSelectedItem());
370        carLoads.setHazardous(type, (String) loadComboBox.getSelectedItem(),
371                hazardousComboBox.getSelectedItem().equals(Bundle.getMessage("ButtonYes")));
372        carLoads.setPickupComment(type, (String) loadComboBox.getSelectedItem(), pickupCommentTextField.getText());
373        carLoads.setDropComment(type, (String) loadComboBox.getSelectedItem(), dropCommentTextField.getText());
374    }
375
376    // replace load name for all car types
377    private void replaceAllLoads(String oldLoad, String newLoad) {
378        for (String type : carTypes.getNames()) {
379            carLoads.addName(type, newLoad);
380            replaceLoad(type, oldLoad, newLoad);
381            carLoads.deleteName(type, oldLoad);
382        }
383    }
384
385    private void replaceLoad(String type, String oldLoad, String newLoad) {
386        // adjust all cars
387        InstanceManager.getDefault(CarManager.class).replaceLoad(type, oldLoad, newLoad);
388        // now adjust schedules
389        InstanceManager.getDefault(ScheduleManager.class).replaceLoad(type, oldLoad, newLoad);
390        // now adjust trains
391        InstanceManager.getDefault(TrainManager.class).replaceLoad(type, oldLoad, newLoad);
392        // now adjust tracks
393        InstanceManager.getDefault(LocationManager.class).replaceLoad(type, oldLoad, newLoad);
394    }
395
396    boolean showQuanity = false;
397
398    public void toggleShowQuanity() {
399        if (showQuanity) {
400            showQuanity = false;
401        } else {
402            showQuanity = true;
403        }
404        quanity.setVisible(showQuanity);
405        updateCarQuanity();
406    }
407
408    private void updateCarQuanity() {
409        if (!showQuanity) {
410            return;
411        }
412        int number = 0;
413        String item = (String) loadComboBox.getSelectedItem();
414        for (Car car : InstanceManager.getDefault(CarManager.class).getList()) {
415            if (car.getLoadName().equals(item)) {
416                number++;
417            }
418        }
419        quanity.setText(Integer.toString(number));
420    }
421
422    private void updateLoadComboBox() {
423        carLoads.updateComboBox(_type, loadComboBox);
424        loadComboBox.setSelectedItem(addTextBox.getText().trim());
425    }
426
427    private void updateLoadType() {
428        String loadName = (String) loadComboBox.getSelectedItem();
429        loadTypeComboBox.setSelectedItem(carLoads.getLoadType(_type, loadName));
430        if (loadName != null &&
431                (loadName.equals(InstanceManager.getDefault(CarLoads.class).getDefaultEmptyName()) ||
432                        loadName.equals(InstanceManager.getDefault(CarLoads.class)
433                                .getDefaultLoadName()))) {
434            loadTypeComboBox.setEnabled(false);
435        } else {
436            loadTypeComboBox.setEnabled(true);
437        }
438    }
439
440    private void updatePriority() {
441        priorityComboBox.setSelectedItem(carLoads.getPriority(_type, (String) loadComboBox.getSelectedItem()));
442    }
443
444    private void updateHazardous() {
445        hazardousComboBox.setSelectedItem(carLoads.isHazardous(_type, (String) loadComboBox.getSelectedItem())
446                ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo"));
447    }
448
449    private void updateCarCommentFields() {
450        pickupCommentTextField.setText(carLoads.getPickupComment(_type, (String) loadComboBox.getSelectedItem()));
451        dropCommentTextField.setText(carLoads.getDropComment(_type, (String) loadComboBox.getSelectedItem()));
452    }
453
454    private void enableButtons() {
455        addButton.setEnabled(_type != null);
456        deleteButton.setEnabled(_type != null);
457        replaceButton.setEnabled(_type != null);
458        saveButton.setEnabled(_type != null);
459    }
460
461    @Override
462    public void dispose() {
463        carLoads.removePropertyChangeListener(this);
464        super.dispose();
465    }
466
467    @Override
468    public void propertyChange(java.beans.PropertyChangeEvent e) {
469        if (Control.SHOW_PROPERTY) {
470            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
471                    .getNewValue());
472        }
473        if (e.getPropertyName().equals(CarLoads.LOAD_CHANGED_PROPERTY)) {
474            updateLoadComboBox();
475        }
476    }
477
478    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarLoadEditFrame.class);
479}