001package jmri.jmrit.operations.rollingstock.cars.gui;
002
003import java.awt.GridBagLayout;
004import java.text.*;
005import java.util.List;
006import java.util.ResourceBundle;
007
008import javax.swing.*;
009
010import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
011import jmri.InstanceManager;
012import jmri.jmrit.operations.rollingstock.*;
013import jmri.jmrit.operations.rollingstock.cars.*;
014import jmri.jmrit.operations.rollingstock.cars.tools.CarAttributeEditFrame;
015import jmri.jmrit.operations.rollingstock.cars.tools.CarLoadEditFrame;
016import jmri.jmrit.operations.setup.Setup;
017import jmri.util.swing.JmriJOptionPane;
018
019/**
020 * Frame for user edit of car
021 *
022 * @author Dan Boudreau Copyright (C) 2008, 2010, 2011, 2014, 2018
023 */
024public class CarEditFrame extends RollingStockEditFrame {
025
026    protected static final ResourceBundle rb = ResourceBundle
027            .getBundle("jmri.jmrit.operations.rollingstock.cars.JmritOperationsCarsBundle");
028
029    CarManager carManager = InstanceManager.getDefault(CarManager.class);
030    CarManagerXml managerXml = InstanceManager.getDefault(CarManagerXml.class);
031
032    // labels
033    JLabel textWeightOz = new JLabel(Bundle.getMessage("WeightOz"));
034
035    JButton editColorButton = new JButton(Bundle.getMessage("ButtonEdit"));
036    JButton editLoadButton = new JButton(Bundle.getMessage("ButtonEdit"));
037    JButton fillWeightButton = new JButton(Bundle.getMessage("Calculate"));
038
039    JCheckBox passengerCheckBox = new JCheckBox(Bundle.getMessage("Passenger"));
040    JCheckBox cabooseCheckBox = new JCheckBox(Bundle.getMessage("Caboose"));
041    JCheckBox fredCheckBox = new JCheckBox(Bundle.getMessage("Fred"));
042    JCheckBox utilityCheckBox = new JCheckBox(Bundle.getMessage("Utility"));
043    JCheckBox hazardousCheckBox = new JCheckBox(Bundle.getMessage("Hazardous"));
044    JCheckBox autoWeightCheckBox = new JCheckBox(Bundle.getMessage("Auto"));
045    
046    JComboBox<String> colorComboBox = InstanceManager.getDefault(CarColors.class).getComboBox();
047    JComboBox<String> loadComboBox = InstanceManager.getDefault(CarLoads.class).getComboBox(null);
048
049    CarLoadEditFrame carLoadEditFrame;
050
051    public CarEditFrame() {
052        super(Bundle.getMessage("TitleCarAdd"));
053    }
054
055    @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Checks for null")
056    @Override
057    public void initComponents() {
058
059        groupComboBox = InstanceManager.getDefault(KernelManager.class).getComboBox();
060
061        super.initComponents();
062
063        addButton.setText(Bundle.getMessage("TitleCarAdd"));
064
065        // type options for cars
066        addItem(pTypeOptions, passengerCheckBox, 0, 1);
067        addItem(pTypeOptions, cabooseCheckBox, 1, 1);
068        addItem(pTypeOptions, fredCheckBox, 2, 1);
069        addItem(pTypeOptions, utilityCheckBox, 3, 1);
070        addItem(pTypeOptions, hazardousCheckBox, 4, 1);
071
072        // default check box selections
073        autoWeightCheckBox.setSelected(true);
074
075        // load tool tips
076        weightTextField.setToolTipText(Bundle.getMessage("TipCarWeightOz"));
077        weightTonsTextField.setToolTipText(Bundle.getMessage("TipCarWeightTons"));
078        autoWeightCheckBox.setToolTipText(Bundle.getMessage("TipCarAutoCalculate"));
079        passengerCheckBox.setToolTipText(Bundle.getMessage("TipCarPassenger"));
080        cabooseCheckBox.setToolTipText(Bundle.getMessage("TipCarCaboose"));
081        fredCheckBox.setToolTipText(Bundle.getMessage("TipCarFred"));
082        utilityCheckBox.setToolTipText(Bundle.getMessage("TipCarUtility"));
083        hazardousCheckBox.setToolTipText(Bundle.getMessage("TipCarHazardous"));
084        blockingTextField.setToolTipText(Bundle.getMessage("TipPassengerCarBlocking"));
085        fillWeightButton.setToolTipText(Bundle.getMessage("TipCalculateCarWeight"));
086        builtTextField.setToolTipText(Bundle.getMessage("TipBuildDate"));
087        valueTextArea.setToolTipText(Bundle.getMessage("TipValue"));
088
089        editColorButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace",
090                Bundle.getMessage("Color").toLowerCase()));
091        editLoadButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace",
092                Bundle.getMessage("load"))); // initial caps for some languages i.e. German
093        editGroupButton.setToolTipText(Bundle.getMessage("TipAddDeleteReplace",
094                Bundle.getMessage("Kernel").toLowerCase()));
095        
096        deleteButton.setToolTipText(Bundle.getMessage("TipDeleteButton"));
097        addButton.setToolTipText(Bundle.getMessage("TipAddButton"));
098        saveButton.setToolTipText(Bundle.getMessage("TipSaveButton"));
099
100        // row 7
101        pWeightOz.setLayout(new GridBagLayout());
102        addItem(pWeightOz, textWeightOz, 0, 0);
103        addItem(pWeightOz, weightTextField, 1, 0);
104        addItem(pWeightOz, fillWeightButton, 2, 0);
105        addItem(pWeightOz, autoWeightCheckBox, 3, 0);
106
107        // row 8
108        pColor.setLayout(new GridBagLayout());
109        pColor.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Color")));
110        addItem(pColor, colorComboBox, 1, 0);
111        addItem(pColor, editColorButton, 2, 0);
112        pColor.setVisible(true);
113
114        // row 9
115        pLoad.setLayout(new GridBagLayout());
116        pLoad.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Load")));
117        addItem(pLoad, loadComboBox, 1, 0);
118        addItem(pLoad, editLoadButton, 2, 0);
119        pLoad.setVisible(true);
120        
121        // select first item so load combobox will update
122        typeComboBox.setSelectedIndex(0);
123
124        // row 10
125        pGroup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Kernel")));
126
127        addEditButtonAction(editColorButton);
128        addButtonAction(fillWeightButton);
129        addButtonAction(editLoadButton);
130
131        // setup check boxes
132        addCheckBoxAction(cabooseCheckBox);
133        addCheckBoxAction(fredCheckBox);
134        addCheckBoxAction(passengerCheckBox);
135        
136        addHelpMenu("package.jmri.jmrit.operations.Operations_CarsEdit", true); // NOI18N
137    }
138
139    @Override
140    protected ResourceBundle getRb() {
141        return rb;
142    }
143
144    @Override
145    protected RollingStockAttribute getTypeManager() {
146        return InstanceManager.getDefault(CarTypes.class);
147    }
148
149    @Override
150    protected RollingStockAttribute getLengthManager() {
151        return InstanceManager.getDefault(CarLengths.class);
152    }
153
154    public void load(Car car) {
155        setTitle(Bundle.getMessage("TitleCarEdit"));
156        super.load(car);
157
158        passengerCheckBox.setSelected(car.isPassenger());
159        cabooseCheckBox.setSelected(car.isCaboose());
160        utilityCheckBox.setSelected(car.isUtility());
161        fredCheckBox.setSelected(car.hasFred());
162        hazardousCheckBox.setSelected(car.isCarHazardous());
163
164        pBlocking.setVisible(car.isPassenger() || car.getKernel() != null);
165
166        if (!InstanceManager.getDefault(CarLoads.class).containsName(car.getTypeName(), car.getLoadName())) {
167            if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("loadNameNotExist",
168                    car.getLoadName()), Bundle.getMessage("addLoad"),
169                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
170                InstanceManager.getDefault(CarLoads.class).addName(car.getTypeName(), car.getLoadName());
171            }
172        }
173        InstanceManager.getDefault(CarLoads.class).updateComboBox(car.getTypeName(), loadComboBox);
174        loadComboBox.setSelectedItem(car.getLoadName());
175        
176        // listen for changes in car load
177        car.addPropertyChangeListener(this);
178
179        // only cars have color attribute
180        if (!InstanceManager.getDefault(CarColors.class).containsName(car.getColor())) {
181            if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("colorNameNotExist",
182                    car.getColor()), Bundle.getMessage("carAddColor"),
183                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
184                InstanceManager.getDefault(CarColors.class).addName(car.getColor());
185            }
186        }
187        colorComboBox.setSelectedItem(car.getColor());
188        groupComboBox.setSelectedItem(car.getKernelName());
189    }
190
191    @Override
192    public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
193        if (ae.getSource() == typeComboBox && typeComboBox.getSelectedItem() != null) {
194            log.debug("Type comboBox sees change, update car loads");
195            InstanceManager.getDefault(CarLoads.class).updateComboBox((String) typeComboBox.getSelectedItem(),
196                    loadComboBox);
197            if (_rs != null) {
198                loadComboBox.setSelectedItem(((Car)_rs).getLoadName());
199            }
200        }
201        if (ae.getSource() == lengthComboBox && autoWeightCheckBox.isSelected()) {
202            calculateWeight();
203        }
204        super.comboBoxActionPerformed(ae);
205    }
206
207    @Override
208    public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) {
209        if (ae.getSource() == cabooseCheckBox && cabooseCheckBox.isSelected()) {
210            fredCheckBox.setSelected(false);
211        }
212        if (ae.getSource() == fredCheckBox && fredCheckBox.isSelected()) {
213            cabooseCheckBox.setSelected(false);
214        }
215        if (ae.getSource() == passengerCheckBox) {
216            pBlocking.setVisible(passengerCheckBox.isSelected() || (_rs != null && ((Car) _rs).getKernel() != null));
217        }
218        super.checkBoxActionPerformed(ae);
219    }
220
221    // Save, Delete, Add, Clear, Calculate, Edit Load buttons
222    @Override
223    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
224        super.buttonActionPerformed(ae);
225        if (ae.getSource() == fillWeightButton) {
226            calculateWeight();
227        }
228        if (ae.getSource() == editLoadButton) {
229            if (carLoadEditFrame != null) {
230                carLoadEditFrame.dispose();
231            }
232            carLoadEditFrame = new CarLoadEditFrame();
233            carLoadEditFrame.initComponents((String) typeComboBox.getSelectedItem(),
234                    (String) loadComboBox.getSelectedItem());
235        }
236    }
237
238    @Override
239    protected boolean check(RollingStock car) {
240        // check to see if car with road and number already exists
241        Car existingCar = carManager.getByRoadAndNumber((String) roadComboBox.getSelectedItem(), roadNumberTextField
242                .getText());
243        if (existingCar != null) {
244            if (car == null) {
245                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carRoadExists"), Bundle
246                        .getMessage("carCanNotAdd"), JmriJOptionPane.ERROR_MESSAGE);
247                return false;
248            }
249            // old car with new road or number?
250            if (!existingCar.getId().equals(car.getId())) {
251                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carRoadExists"), Bundle
252                        .getMessage("carCanNotUpdate"), JmriJOptionPane.ERROR_MESSAGE);
253                return false;
254            }
255        }
256        // check car's weight has proper format
257        try {
258            Number number = NumberFormat.getNumberInstance().parse(weightTextField.getText());
259            log.debug("Car weight in oz: {}", number);
260        } catch (Exception e) {
261            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carWeightFormat"), Bundle
262                    .getMessage("carActualWeight"), JmriJOptionPane.ERROR_MESSAGE);
263            return false;
264        }
265
266        return super.check(car);
267    }
268
269    private void calculateWeight() {
270        if (lengthComboBox.getSelectedItem() != null) {
271            String length = (String) lengthComboBox.getSelectedItem();
272            try {
273                String carWeight = CarManager.calculateCarWeight(length);
274                weightTextField.setText(carWeight); // car weight in ounces.
275                int tons = (int) (NumberFormat.getNumberInstance().parse(carWeight).doubleValue() * Setup.getScaleTonRatio());
276                // adjust weight for caboose
277                if (cabooseCheckBox.isSelected() || passengerCheckBox.isSelected()) {
278                    tons = (int) (Double.parseDouble(length) * .9); // .9 tons/foot
279                }
280                weightTonsTextField.setText(Integer.toString(tons));
281            } catch (NumberFormatException e) {
282                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carLengthMustBe"), Bundle
283                        .getMessage("carWeigthCanNot"), JmriJOptionPane.ERROR_MESSAGE);
284            } catch (ParseException ex) {
285                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carWeightFormat"), Bundle
286                        .getMessage("carWeigthCanNot"), JmriJOptionPane.ERROR_MESSAGE);
287            }
288        }
289    }
290
291    @Override
292    protected void save(boolean isSave) {
293        if (roadComboBox.getSelectedItem() == null) {
294            return;
295        }
296        super.save(carManager, isSave);
297        Car car = (Car) _rs;
298        
299        if (colorComboBox.getSelectedItem() != null) {
300            car.setColor((String) colorComboBox.getSelectedItem());
301        }
302
303        // ask if all cars of this type should be passenger 
304        if (isSave && car.isPassenger() ^ passengerCheckBox.isSelected()) {
305            if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(passengerCheckBox.isSelected() ? Bundle
306                    .getMessage("carModifyTypePassenger") : Bundle.getMessage("carRemoveTypePassenger"),
307                    new Object[]{car.getTypeName()}),
308                    Bundle.getMessage("carModifyAllType",
309                            car.getTypeName()),
310                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
311                // go through the entire list and change the passenger setting
312                // for all cars of this type
313                for (Car c : carManager.getList()) {
314                    if (c.getTypeName().equals(car.getTypeName())) {
315                        c.setPassenger(passengerCheckBox.isSelected());
316                    }
317                }
318            }
319        }
320        car.setPassenger(passengerCheckBox.isSelected());
321        int blocking = Integer.parseInt(blockingTextField.getText());
322        // ask if blocking order should be the same
323        if (isSave && car.getKernel() == null && passengerCheckBox.isSelected() && car.getBlocking() != blocking) {
324            if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("carChangeBlocking",
325                    blocking, car.getTypeName()),
326                    Bundle.getMessage("carModifyAllType", car.getTypeName()),
327                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
328                // go through the entire list and change the passenger setting
329                // for all cars of this type
330                for (Car c : carManager.getList()) {
331                    if (c.isPassenger() && c.getTypeName().equals(car.getTypeName())) {
332                        c.setBlocking(blocking);
333                    }
334                }
335            }
336        }
337        car.setBlocking(blocking);
338        // ask if all cars of this type should be caboose
339        if (isSave && car.isCaboose() ^ cabooseCheckBox.isSelected()) {
340            if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(cabooseCheckBox.isSelected() ? Bundle
341                    .getMessage("carModifyTypeCaboose") : Bundle.getMessage("carRemoveTypeCaboose"),
342                    new Object[]{car.getTypeName()}),
343                    Bundle.getMessage("carModifyAllType",
344                            car.getTypeName()),
345                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
346                // go through the entire list and change the caboose setting for all cars of this type
347                for (Car c : carManager.getList()) {
348                    if (c.getTypeName().equals(car.getTypeName())) {
349                        c.setCaboose(cabooseCheckBox.isSelected());
350                    }
351                }
352            }
353        }
354        car.setCaboose(cabooseCheckBox.isSelected());
355        // ask if all cars of this type should be utility
356        if (isSave && car.isUtility() ^ utilityCheckBox.isSelected()) {
357            if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(utilityCheckBox.isSelected() ? Bundle
358                    .getMessage("carModifyTypeUtility") : Bundle.getMessage("carRemoveTypeUtility"),
359                    new Object[]{car.getTypeName()}),
360                    Bundle.getMessage("carModifyAllType",
361                            car.getTypeName()),
362                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
363                // go through the entire list and change the utility for all cars of this type
364                for (Car c : carManager.getList()) {
365                    if (c.getTypeName().equals(car.getTypeName())) {
366                        c.setUtility(utilityCheckBox.isSelected());
367                    }
368                }
369            }
370        }
371        car.setUtility(utilityCheckBox.isSelected());
372        // ask if all cars of this type should be hazardous
373        if (isSave && car.isCarHazardous() ^ hazardousCheckBox.isSelected()) {
374            if (JmriJOptionPane.showConfirmDialog(this, MessageFormat.format(hazardousCheckBox.isSelected() ? Bundle
375                    .getMessage("carModifyTypeHazardous") : Bundle.getMessage("carRemoveTypeHazardous"),
376                    new Object[]{car.getTypeName()}),
377                    Bundle.getMessage("carModifyAllType",
378                            car.getTypeName()),
379                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
380                // go through the entire list and change the hazardous setting for all cars of this type
381                for (Car c : carManager.getList()) {
382                    if (c.getTypeName().equals(car.getTypeName())) {
383                        c.setCarHazardous(hazardousCheckBox.isSelected());
384                    }
385                }
386            }
387        }
388        car.setCarHazardous(hazardousCheckBox.isSelected());
389        car.setFred(fredCheckBox.isSelected());
390        if (groupComboBox.getSelectedItem() != null) {
391            if (groupComboBox.getSelectedItem().equals(CarManager.NONE)) {
392                car.setKernel(null);
393                if (!car.isPassenger()) {
394                    car.setBlocking(Car.DEFAULT_BLOCKING_ORDER);
395                }
396            } else if (!car.getKernelName().equals(groupComboBox.getSelectedItem())) {
397                car.setKernel(InstanceManager.getDefault(KernelManager.class).getKernelByName((String) groupComboBox.getSelectedItem()));
398                // if car has FRED or caboose make lead
399                if (car.hasFred() || car.isCaboose()) {
400                    car.getKernel().setLead(car);
401                }
402                car.setBlocking(car.getKernel().getSize());
403            }
404        }
405        if (loadComboBox.getSelectedItem() != null && !car.getLoadName().equals(loadComboBox.getSelectedItem())) {
406            car.setLoadName((String) loadComboBox.getSelectedItem());
407            car.setWait(0); // car could be at spur with schedule
408            car.setScheduleItemId(Car.NONE);
409            // check to see if car is part of kernel, and ask if all the other cars in the kernel should be changed
410            if (car.getKernel() != null) {
411                List<Car> cars = car.getKernel().getCars();
412                if (cars.size() > 1) {
413                    if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("carInKernelLoad",
414                            car.toString(), car.getLoadName()),
415                            Bundle.getMessage("carPartKernel",
416                                    car.getKernelName()),
417                            JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.YES_OPTION) {
418                        // go through the entire list and change the loads for all cars
419                        for (Car c : cars) {
420                            if (InstanceManager.getDefault(CarLoads.class).containsName(c.getTypeName(),
421                                    car.getLoadName())) {
422                                c.setLoadName(car.getLoadName());
423                                c.setWait(0); // car could be at spur with schedule
424                                c.setScheduleItemId(Car.NONE);
425                            }
426                        }
427                    }
428                }
429            }
430        }
431        
432        // place car on track after setting load name
433        checkAndSetLocationAndTrack(car);
434
435        // update blocking
436        pBlocking.setVisible(passengerCheckBox.isSelected() || car.getKernel() != null);
437        blockingTextField.setText(Integer.toString(car.getBlocking()));
438
439        // is this car part of a kernel? Ask if all cars should have the same location and track
440        if (car.getKernel() != null) {
441            List<Car> cars = car.getKernel().getCars();
442            for (Car kcar : cars) {
443                if (kcar != car) {
444                    if (kcar.getLocation() != car.getLocation() || kcar.getTrack() != car.getTrack()) {
445                        int results = JmriJOptionPane.showConfirmDialog(this, Bundle
446                                .getMessage("carInKernelLocation",
447                                car.toString(), car.getLocationName(), car.getTrackName()),
448                                Bundle.getMessage("carPartKernel",
449                                                car.getKernelName()),
450                                JmriJOptionPane.YES_NO_OPTION);
451                        if (results == JmriJOptionPane.YES_OPTION) {
452                            // change the location for all cars in kernel
453                            for (Car kcar2 : cars) {
454                                if (kcar2 != car) {
455                                    setLocationAndTrack(kcar2);
456                                }
457                            }
458                        }
459                        break; // done
460                    }
461                }
462            }
463        }
464    }
465    
466    @Override
467    protected void delete() {
468        Car car = carManager.getByRoadAndNumber((String) roadComboBox.getSelectedItem(), roadNumberTextField
469                .getText());
470        if (car != null) {
471            carManager.deregister(car);
472        }
473    }
474
475    CarAttributeEditFrame carAttributeEditFrame;
476
477    // edit buttons only one frame active at a time
478    @Override
479    public void buttonEditActionPerformed(java.awt.event.ActionEvent ae) {
480        if (carAttributeEditFrame != null) {
481            carAttributeEditFrame.dispose();
482        }
483        carAttributeEditFrame = new CarAttributeEditFrame();
484        carAttributeEditFrame.addPropertyChangeListener(this);
485
486        if (ae.getSource() == editRoadButton) {
487            carAttributeEditFrame.initComponents(CarAttributeEditFrame.ROAD, (String) roadComboBox.getSelectedItem());
488        }
489        if (ae.getSource() == editTypeButton) {
490            carAttributeEditFrame.initComponents(CarAttributeEditFrame.TYPE, (String) typeComboBox.getSelectedItem());
491        }
492        if (ae.getSource() == editColorButton) {
493            carAttributeEditFrame.initComponents(CarAttributeEditFrame.COLOR, (String) colorComboBox.getSelectedItem());
494        }
495        if (ae.getSource() == editLengthButton) {
496            carAttributeEditFrame.initComponents(CarAttributeEditFrame.LENGTH,
497                    (String) lengthComboBox.getSelectedItem());
498        }
499        if (ae.getSource() == editOwnerButton) {
500            carAttributeEditFrame.initComponents(CarAttributeEditFrame.OWNER, (String) ownerComboBox.getSelectedItem());
501        }
502        if (ae.getSource() == editGroupButton) {
503            carAttributeEditFrame.initComponents(CarAttributeEditFrame.KERNEL,
504                    (String) groupComboBox.getSelectedItem());
505        }
506    }
507
508    @Override
509    protected void addPropertyChangeListeners() {
510        InstanceManager.getDefault(CarLoads.class).addPropertyChangeListener(this);
511        InstanceManager.getDefault(CarColors.class).addPropertyChangeListener(this);
512        InstanceManager.getDefault(KernelManager.class).addPropertyChangeListener(this);
513        carManager.addPropertyChangeListener(this);
514        super.addPropertyChangeListeners();
515    }
516
517    @Override
518    protected void removePropertyChangeListeners() {
519        InstanceManager.getDefault(CarLoads.class).removePropertyChangeListener(this);
520        InstanceManager.getDefault(CarColors.class).removePropertyChangeListener(this);
521        InstanceManager.getDefault(KernelManager.class).removePropertyChangeListener(this);
522        carManager.removePropertyChangeListener(this);
523        if (_rs != null) {
524            _rs.removePropertyChangeListener(this);
525        }
526        super.removePropertyChangeListeners();
527    }
528    
529    @Override
530    public void dispose() {
531        if (carLoadEditFrame != null) {
532            carLoadEditFrame.dispose();
533        }
534        if (carAttributeEditFrame != null) {
535            carAttributeEditFrame.dispose();
536        }
537        super.dispose();
538    }
539
540    @Override
541    public void propertyChange(java.beans.PropertyChangeEvent e) {
542        //        if (Control.SHOW_PROPERTY) {
543        log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
544                .getNewValue());
545        //        }
546        super.propertyChange(e);
547        
548        if (e.getPropertyName().equals(CarLengths.CARLENGTHS_CHANGED_PROPERTY)) {
549            InstanceManager.getDefault(CarLengths.class).updateComboBox(lengthComboBox);
550            if (_rs != null) {
551                lengthComboBox.setSelectedItem(_rs.getLength());
552            }
553        }
554        if (e.getPropertyName().equals(CarColors.CARCOLORS_CHANGED_PROPERTY)) {
555            InstanceManager.getDefault(CarColors.class).updateComboBox(colorComboBox);
556            if (_rs != null) {
557                colorComboBox.setSelectedItem(_rs.getColor());
558            }
559        }
560        if (e.getPropertyName().equals(KernelManager.LISTLENGTH_CHANGED_PROPERTY) ||
561                e.getPropertyName().equals(Car.KERNEL_NAME_CHANGED_PROPERTY)) {
562            InstanceManager.getDefault(KernelManager.class).updateComboBox(groupComboBox);
563            if (_rs != null) {
564                groupComboBox.setSelectedItem(((Car) _rs).getKernelName());
565            }
566        }
567        if (e.getPropertyName().equals(CarLoads.LOAD_CHANGED_PROPERTY)) {
568            InstanceManager.getDefault(CarLoads.class).updateComboBox((String) typeComboBox.getSelectedItem(),
569                    loadComboBox);
570        }
571        if (e.getPropertyName().equals(Car.LOAD_CHANGED_PROPERTY) ||
572                e.getPropertyName().equals(CarLoads.LOAD_CHANGED_PROPERTY)) {
573            if (_rs != null) {
574                loadComboBox.setSelectedItem(((Car) _rs).getLoadName());
575            }
576        }
577        if (e.getPropertyName().equals(CarAttributeEditFrame.DISPOSE)) {
578            carAttributeEditFrame = null;
579        }
580    }
581
582    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarEditFrame.class);
583}