001package jmri.jmrit.operations.locations.tools;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004import java.awt.Dimension;
005import java.awt.FlowLayout;
006import java.awt.GridBagLayout;
007import javax.swing.BorderFactory;
008import javax.swing.BoxLayout;
009import javax.swing.ButtonGroup;
010import javax.swing.JButton;
011import javax.swing.JCheckBox;
012import javax.swing.JComboBox;
013import javax.swing.JLabel;
014import javax.swing.JMenu;
015import javax.swing.JOptionPane;
016import javax.swing.JPanel;
017import javax.swing.JRadioButton;
018import javax.swing.JScrollPane;
019import jmri.InstanceManager;
020import jmri.jmrit.operations.OperationsFrame;
021import jmri.jmrit.operations.OperationsXml;
022import jmri.jmrit.operations.locations.Location;
023import jmri.jmrit.operations.locations.Track;
024import jmri.jmrit.operations.rollingstock.cars.CarLoad;
025import jmri.jmrit.operations.rollingstock.cars.CarLoads;
026import jmri.jmrit.operations.rollingstock.cars.CarTypes;
027import jmri.jmrit.operations.setup.Control;
028import jmri.jmrit.operations.setup.Setup;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032/**
033 * Frame for user edit of track loads
034 *
035 * @author Dan Boudreau Copyright (C) 2013, 2014, 2015
036 * 
037 */
038public class TrackLoadEditFrame extends OperationsFrame implements java.beans.PropertyChangeListener {
039
040    private static boolean loadAndType = false;
041    private static boolean shipLoadAndType = false;
042
043    Location _location = null;
044    Track _track = null;
045    String _type = "";
046    JMenu _toolMenu = null;
047
048    // panels
049    JPanel pLoadControls = new JPanel();
050    JPanel panelLoads = new JPanel();
051    JScrollPane paneLoads = new JScrollPane(panelLoads);
052
053    JPanel pShipLoadControls = new JPanel();
054    JPanel panelShipLoads = new JPanel();
055    JScrollPane paneShipLoadControls;
056    JScrollPane paneShipLoads = new JScrollPane(panelShipLoads);
057
058    // major buttons
059    JButton saveTrackButton = new JButton(Bundle.getMessage("SaveTrack"));
060
061    JButton addLoadButton = new JButton(Bundle.getMessage("AddLoad"));
062    JButton deleteLoadButton = new JButton(Bundle.getMessage("DeleteLoad"));
063    JButton deleteAllLoadsButton = new JButton(Bundle.getMessage("DeleteAll"));
064
065    JButton addShipLoadButton = new JButton(Bundle.getMessage("AddLoad"));
066    JButton deleteShipLoadButton = new JButton(Bundle.getMessage("DeleteLoad"));
067    JButton deleteAllShipLoadsButton = new JButton(Bundle.getMessage("DeleteAll"));
068
069    // check boxes
070    JCheckBox loadAndTypeCheckBox = new JCheckBox(Bundle.getMessage("TypeAndLoad"));
071    JCheckBox shipLoadAndTypeCheckBox = new JCheckBox(Bundle.getMessage("TypeAndLoad"));
072    JCheckBox holdCars = new JCheckBox();
073
074    // radio buttons
075    JRadioButton loadNameAll = new JRadioButton(Bundle.getMessage("AcceptAll"));
076    JRadioButton loadNameInclude = new JRadioButton(Bundle.getMessage("AcceptOnly"));
077    JRadioButton loadNameExclude = new JRadioButton(Bundle.getMessage("Exclude"));
078
079    JRadioButton shipLoadNameAll = new JRadioButton(Bundle.getMessage("ShipAll"));
080    JRadioButton shipLoadNameInclude = new JRadioButton(Bundle.getMessage("ShipOnly"));
081    JRadioButton shipLoadNameExclude = new JRadioButton(Bundle.getMessage("Exclude"));
082
083    // combo box
084    JComboBox<String> comboBoxLoads = InstanceManager.getDefault(CarLoads.class).getComboBox(null);
085    JComboBox<String> comboBoxShipLoads = InstanceManager.getDefault(CarLoads.class).getComboBox(null);
086    JComboBox<String> comboBoxTypes = InstanceManager.getDefault(CarTypes.class).getComboBox();
087    JComboBox<String> comboBoxShipTypes = InstanceManager.getDefault(CarTypes.class).getComboBox();
088
089    // labels
090    JLabel trackName = new JLabel();
091
092    public static final String DISPOSE = "dispose"; // NOI18N
093    public static final int MAX_NAME_LENGTH = Control.max_len_string_track_name;
094
095    public TrackLoadEditFrame() {
096        super(Bundle.getMessage("TitleEditTrackLoads"));
097    }
098
099    public void initComponents(Location location, Track track) {
100        _location = location;
101        _track = track;
102
103        // property changes
104        _location.addPropertyChangeListener(this);
105        // listen for car load name and type changes
106        InstanceManager.getDefault(CarLoads.class).addPropertyChangeListener(this);
107        InstanceManager.getDefault(CarTypes.class).addPropertyChangeListener(this);
108
109        // the following code sets the frame's initial state
110        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
111
112        // Set up the panels
113        // Layout the panel by rows
114        // row 1
115        JPanel p1 = new JPanel();
116        p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
117        p1.setMaximumSize(new Dimension(2000, 250));
118
119        // row 1a
120        JPanel pTrackName = new JPanel();
121        pTrackName.setLayout(new GridBagLayout());
122        pTrackName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Track")));
123        addItem(pTrackName, trackName, 0, 0);
124
125        // row 1b
126        JPanel pLocationName = new JPanel();
127        pLocationName.setLayout(new GridBagLayout());
128        pLocationName.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Location")));
129        addItem(pLocationName, new JLabel(_location.getName()), 0, 0);
130
131        p1.add(pTrackName);
132        p1.add(pLocationName);
133
134        // row 3
135        JPanel p3 = new JPanel();
136        p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
137        JScrollPane pane3 = new JScrollPane(p3);
138        pane3.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LoadsTrack")));
139        pane3.setMaximumSize(new Dimension(2000, 400));
140
141        JPanel pLoadRadioButtons = new JPanel();
142        pLoadRadioButtons.setLayout(new FlowLayout());
143
144        pLoadRadioButtons.add(loadNameAll);
145        pLoadRadioButtons.add(loadNameInclude);
146        pLoadRadioButtons.add(loadNameExclude);
147        pLoadRadioButtons.add(loadAndTypeCheckBox);
148
149        pLoadControls.setLayout(new FlowLayout());
150
151        pLoadControls.add(comboBoxTypes);
152        pLoadControls.add(comboBoxLoads);
153        pLoadControls.add(addLoadButton);
154        pLoadControls.add(deleteLoadButton);
155        pLoadControls.add(deleteAllLoadsButton);
156
157        pLoadControls.setVisible(false);
158
159        p3.add(pLoadRadioButtons);
160        p3.add(pLoadControls);
161
162        // row 4
163        panelLoads.setLayout(new GridBagLayout());
164        paneLoads.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Loads")));
165
166        ButtonGroup loadGroup = new ButtonGroup();
167        loadGroup.add(loadNameAll);
168        loadGroup.add(loadNameInclude);
169        loadGroup.add(loadNameExclude);
170
171        // row 6
172        JPanel p6 = new JPanel();
173        p6.setLayout(new BoxLayout(p6, BoxLayout.Y_AXIS));
174        paneShipLoadControls = new JScrollPane(p6);
175        paneShipLoadControls.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("ShipLoadsTrack")));
176        paneShipLoadControls.setMaximumSize(new Dimension(2000, 400));
177
178        JPanel pShipLoadRadioButtons = new JPanel();
179        pShipLoadRadioButtons.setLayout(new FlowLayout());
180
181        pShipLoadRadioButtons.add(shipLoadNameAll);
182        pShipLoadRadioButtons.add(shipLoadNameInclude);
183        pShipLoadRadioButtons.add(shipLoadNameExclude);
184        pShipLoadRadioButtons.add(shipLoadAndTypeCheckBox);
185
186        pShipLoadControls.setLayout(new FlowLayout());
187
188        pShipLoadControls.add(comboBoxShipTypes);
189        pShipLoadControls.add(comboBoxShipLoads);
190        pShipLoadControls.add(addShipLoadButton);
191        pShipLoadControls.add(deleteShipLoadButton);
192        pShipLoadControls.add(deleteAllShipLoadsButton);
193
194        pShipLoadControls.setVisible(false);
195
196        p6.add(pShipLoadRadioButtons);
197        p6.add(pShipLoadControls);
198
199        // row 7
200        panelShipLoads.setLayout(new GridBagLayout());
201        paneShipLoads.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Loads")));
202
203        ButtonGroup shipLoadGroup = new ButtonGroup();
204        shipLoadGroup.add(shipLoadNameAll);
205        shipLoadGroup.add(shipLoadNameInclude);
206        shipLoadGroup.add(shipLoadNameExclude);
207        
208        JPanel pOptions = new JPanel();
209        pOptions.setLayout(new GridBagLayout());
210        pOptions.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Options")));
211        pOptions.setMaximumSize(new Dimension(2000, 400));
212        addItem(pOptions, holdCars, 0, 0);
213        holdCars.setText(Bundle.getMessage("HoldCarsWithCustomLoads"));
214        holdCars.setToolTipText(Bundle.getMessage("HoldCarsWithCustomLoadsTip"));
215
216        // row 12
217        JPanel panelButtons = new JPanel();
218        panelButtons.setLayout(new GridBagLayout());
219        panelButtons.setBorder(BorderFactory.createTitledBorder(""));
220        panelButtons.setMaximumSize(new Dimension(2000, 200));
221
222        // row 13
223        addItem(panelButtons, saveTrackButton, 0, 0);
224
225        getContentPane().add(p1);
226        getContentPane().add(pane3);
227        getContentPane().add(paneLoads);
228        getContentPane().add(paneShipLoadControls);
229        getContentPane().add(paneShipLoads);
230        getContentPane().add(pOptions);
231        getContentPane().add(panelButtons);
232
233        // setup buttons
234        addButtonAction(saveTrackButton);
235
236        addButtonAction(deleteLoadButton);
237        addButtonAction(deleteAllLoadsButton);
238        addButtonAction(addLoadButton);
239
240        addButtonAction(deleteShipLoadButton);
241        addButtonAction(deleteAllShipLoadsButton);
242        addButtonAction(addShipLoadButton);
243
244        addRadioButtonAction(loadNameAll);
245        addRadioButtonAction(loadNameInclude);
246        addRadioButtonAction(loadNameExclude);
247
248        addRadioButtonAction(shipLoadNameAll);
249        addRadioButtonAction(shipLoadNameInclude);
250        addRadioButtonAction(shipLoadNameExclude);
251
252        addComboBoxAction(comboBoxTypes);
253        addComboBoxAction(comboBoxShipTypes);
254
255        paneShipLoadControls.setVisible(false);
256        paneShipLoads.setVisible(false);
257        pOptions.setVisible(false);
258
259        // load fields and enable buttons
260        if (_track != null) {
261            _track.addPropertyChangeListener(this);
262            trackName.setText(_track.getName());
263            // only show ship loads for staging tracks
264            paneShipLoadControls.setVisible(_track.isStaging());
265            paneShipLoads.setVisible(_track.isStaging());
266            pOptions.setVisible(_track.isSpur());
267            holdCars.setSelected(_track.isHoldCarsWithCustomLoadsEnabled());
268            updateButtons(true);
269        } else {
270            updateButtons(false);
271        }
272
273        // build menu
274        // JMenuBar menuBar = new JMenuBar();
275        // _toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
276        // menuBar.add(_toolMenu);
277        // setJMenuBar(menuBar);
278        // load
279        updateTypeComboBoxes();
280        updateLoadComboBoxes();
281        updateLoadNames();
282        updateShipLoadNames();
283
284        loadAndTypeCheckBox.setSelected(loadAndType);
285        shipLoadAndTypeCheckBox.setSelected(shipLoadAndType);
286        
287        // add help menu to window
288        addHelpMenu("package.jmri.jmrit.operations.Operations_LoadOptions", true); // NOI18N
289
290        initMinimumSize(new Dimension(Control.panelWidth600, Control.panelHeight400));
291    }
292
293    // Save, Delete, Add
294    @Override
295    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
296        if (_track == null) {
297            return;
298        }
299        if (ae.getSource() == saveTrackButton) {
300            log.debug("track save button activated");
301            save();
302            if (Setup.isCloseWindowOnSaveEnabled()) {
303                dispose();
304            }
305        }
306        if (ae.getSource() == addLoadButton) {
307            String loadName = (String) comboBoxLoads.getSelectedItem();
308            if (loadAndTypeCheckBox.isSelected()) {
309                loadName = comboBoxTypes.getSelectedItem() + CarLoad.SPLIT_CHAR + loadName;
310            }
311            _track.addLoadName(loadName);
312            selectNextItemComboBox(comboBoxLoads);
313        }
314        if (ae.getSource() == deleteLoadButton) {
315            String loadName = (String) comboBoxLoads.getSelectedItem();
316            if (loadAndTypeCheckBox.isSelected()) {
317                loadName = comboBoxTypes.getSelectedItem() + CarLoad.SPLIT_CHAR + loadName;
318            }
319            _track.deleteLoadName(loadName);
320            selectNextItemComboBox(comboBoxLoads);
321        }
322        if (ae.getSource() == deleteAllLoadsButton) {
323            deleteAllLoads();
324        }
325        if (ae.getSource() == addShipLoadButton) {
326            String loadName = (String) comboBoxShipLoads.getSelectedItem();
327            if (shipLoadAndTypeCheckBox.isSelected()) {
328                loadName = comboBoxShipTypes.getSelectedItem() + CarLoad.SPLIT_CHAR + loadName;
329            }
330            _track.addShipLoadName(loadName);
331            selectNextItemComboBox(comboBoxShipLoads);
332        }
333        if (ae.getSource() == deleteShipLoadButton) {
334            String loadName = (String) comboBoxShipLoads.getSelectedItem();
335            if (shipLoadAndTypeCheckBox.isSelected()) {
336                loadName = comboBoxShipTypes.getSelectedItem() + CarLoad.SPLIT_CHAR + loadName;
337            }
338            _track.deleteShipLoadName(loadName);
339            selectNextItemComboBox(comboBoxShipLoads);
340        }
341        if (ae.getSource() == deleteAllShipLoadsButton) {
342            deleteAllShipLoads();
343        }
344    }
345
346    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "GUI ease of use")
347    protected void save() {
348        checkForErrors();
349        _track.setHoldCarsWithCustomLoadsEnabled(holdCars.isSelected());
350        // save the last state of the "Use car type and load" checkbox
351        loadAndType = loadAndTypeCheckBox.isSelected();
352        shipLoadAndType = shipLoadAndTypeCheckBox.isSelected();
353        // save location file
354        OperationsXml.save();
355    }
356
357    protected void updateButtons(boolean enabled) {
358        saveTrackButton.setEnabled(enabled);
359
360        loadNameAll.setEnabled(enabled);
361        loadNameInclude.setEnabled(enabled);
362        loadNameExclude.setEnabled(enabled);
363        loadAndTypeCheckBox.setEnabled(enabled);
364
365        // enable ship options if any of the three generate loads from staging is selected
366        // or if there are any ship load restrictions for this track
367        boolean en = enabled
368                && (_track.isAddCustomLoadsAnyStagingTrackEnabled() || _track.isAddCustomLoadsAnySpurEnabled() || _track
369                .isAddCustomLoadsEnabled() || !_track.getShipLoadOption().equals(Track.ALL_LOADS));
370
371        shipLoadNameAll.setEnabled(en);
372        shipLoadNameInclude.setEnabled(en);
373        shipLoadNameExclude.setEnabled(en);
374        shipLoadAndTypeCheckBox.setEnabled(en);
375
376        addShipLoadButton.setEnabled(en);
377        deleteShipLoadButton.setEnabled(en);
378        deleteAllShipLoadsButton.setEnabled(en);
379
380        comboBoxShipLoads.setEnabled(en);
381        comboBoxShipTypes.setEnabled(en);
382
383    }
384
385    @Override
386    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
387        log.debug("radio button activated");
388        if (ae.getSource() == loadNameAll) {
389            _track.setLoadOption(Track.ALL_LOADS);
390        }
391        if (ae.getSource() == loadNameInclude) {
392            _track.setLoadOption(Track.INCLUDE_LOADS);
393        }
394        if (ae.getSource() == loadNameExclude) {
395            _track.setLoadOption(Track.EXCLUDE_LOADS);
396        }
397        if (ae.getSource() == shipLoadNameAll) {
398            _track.setShipLoadOption(Track.ALL_LOADS);
399        }
400        if (ae.getSource() == shipLoadNameInclude) {
401            _track.setShipLoadOption(Track.INCLUDE_LOADS);
402        }
403        if (ae.getSource() == shipLoadNameExclude) {
404            _track.setShipLoadOption(Track.EXCLUDE_LOADS);
405        }
406    }
407
408    // Car type combo box has been changed, show loads associated with this car type
409    @Override
410    public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) {
411        updateLoadComboBoxes();
412    }
413
414    private void updateLoadComboBoxes() {
415        String carType = (String) comboBoxTypes.getSelectedItem();
416        InstanceManager.getDefault(CarLoads.class).updateComboBox(carType, comboBoxLoads);
417        carType = (String) comboBoxShipTypes.getSelectedItem();
418        InstanceManager.getDefault(CarLoads.class).updateComboBox(carType, comboBoxShipLoads);
419    }
420
421    private void updateLoadNames() {
422        log.debug("Update load names");
423        panelLoads.removeAll();
424        if (_track != null) {
425            // set radio button
426            loadNameAll.setSelected(_track.getLoadOption().equals(Track.ALL_LOADS));
427            loadNameInclude.setSelected(_track.getLoadOption().equals(Track.INCLUDE_LOADS));
428            loadNameExclude.setSelected(_track.getLoadOption().equals(Track.EXCLUDE_LOADS));
429
430            pLoadControls.setVisible(!loadNameAll.isSelected());
431
432            if (!loadNameAll.isSelected()) {
433                int x = 0;
434                int y = 0; // vertical position in panel
435
436                int numberOfLoads = getNumberOfCheckboxesPerLine() / 2 + 1;
437                for (String loadName : _track.getLoadNames()) {
438                    JLabel load = new JLabel();
439                    load.setText(loadName);
440                    addItemTop(panelLoads, load, x++, y);
441                    // limit the number of loads per line
442                    if (x > numberOfLoads) {
443                        y++;
444                        x = 0;
445                    }
446                }
447                revalidate();
448            }
449        } else {
450            loadNameAll.setSelected(true);
451        }
452        panelLoads.repaint();
453        panelLoads.revalidate();
454    }
455
456    private void updateShipLoadNames() {
457        log.debug("Update ship load names");
458        panelShipLoads.removeAll();
459        if (_track != null) {
460            // set radio button
461            shipLoadNameAll.setSelected(_track.getShipLoadOption().equals(Track.ALL_LOADS));
462            shipLoadNameInclude.setSelected(_track.getShipLoadOption().equals(Track.INCLUDE_LOADS));
463            shipLoadNameExclude.setSelected(_track.getShipLoadOption().equals(Track.EXCLUDE_LOADS));
464
465            pShipLoadControls.setVisible(!shipLoadNameAll.isSelected());
466
467            if (!shipLoadNameAll.isSelected()) {
468                int x = 0;
469                int y = 0; // vertical position in panel
470
471                int numberOfLoads = getNumberOfCheckboxesPerLine() / 2 + 1;
472                for (String loadName : _track.getShipLoadNames()) {
473                    JLabel load = new JLabel();
474                    load.setText(loadName);
475                    addItemTop(panelShipLoads, load, x++, y);
476                    // limit the number of loads per line
477                    if (x > numberOfLoads) {
478                        y++;
479                        x = 0;
480                    }
481                }
482                revalidate();
483            }
484        } else {
485            shipLoadNameAll.setSelected(true);
486        }
487        panelShipLoads.repaint();
488        panelShipLoads.revalidate();
489    }
490
491    private void deleteAllLoads() {
492        if (_track != null) {
493            for (String loadName : _track.getLoadNames()) {
494                _track.deleteLoadName(loadName);
495            }
496        }
497    }
498
499    private void deleteAllShipLoads() {
500        if (_track != null) {
501            for (String loadName : _track.getShipLoadNames()) {
502                _track.deleteShipLoadName(loadName);
503            }
504        }
505    }
506
507    private void updateTypeComboBoxes() {
508        InstanceManager.getDefault(CarTypes.class).updateComboBox(comboBoxTypes);
509        // remove car types not serviced by this location and track
510        for (int i = comboBoxTypes.getItemCount() - 1; i >= 0; i--) {
511            String type = comboBoxTypes.getItemAt(i);
512            if (_track != null && !_track.isTypeNameAccepted(type)) {
513                comboBoxTypes.removeItem(type);
514            }
515        }
516        InstanceManager.getDefault(CarTypes.class).updateComboBox(comboBoxShipTypes);
517        // remove car types not serviced by this location and track
518        for (int i = comboBoxShipTypes.getItemCount() - 1; i >= 0; i--) {
519            String type = comboBoxShipTypes.getItemAt(i);
520            if (_track != null && !_track.isTypeNameAccepted(type)) {
521                comboBoxShipTypes.removeItem(type);
522            }
523        }
524    }
525
526    private void checkForErrors() {
527        if (_track.getLoadOption().equals(Track.INCLUDE_LOADS) && _track.getLoadNames().length == 0
528                || _track.getShipLoadOption().equals(Track.INCLUDE_LOADS) && _track.getShipLoadNames().length == 0) {
529            JOptionPane.showMessageDialog(this, Bundle.getMessage("ErrorNeedLoads"), Bundle.getMessage("ErrorNoLoads"),
530                    JOptionPane.ERROR_MESSAGE);
531        }
532    }
533
534    @Override
535    public void dispose() {
536        if (_track != null) {
537            _track.removePropertyChangeListener(this);
538        }
539        _location.removePropertyChangeListener(this);
540        InstanceManager.getDefault(CarLoads.class).removePropertyChangeListener(this);
541        InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this);
542        super.dispose();
543    }
544
545    @Override
546    public void propertyChange(java.beans.PropertyChangeEvent e) {
547        if (Control.SHOW_PROPERTY) {
548            log.debug("Property change ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e.getNewValue()); // NOI18N
549        }
550        if (e.getPropertyName().equals(Location.TYPES_CHANGED_PROPERTY)
551                || e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY)
552                || e.getPropertyName().equals(Track.TYPES_CHANGED_PROPERTY)) {
553            updateTypeComboBoxes();
554        }
555        if (e.getPropertyName().equals(CarLoads.LOAD_NAME_CHANGED_PROPERTY)
556                || e.getPropertyName().equals(CarLoads.LOAD_CHANGED_PROPERTY)) {
557            updateLoadComboBoxes();
558            updateLoadNames();
559            updateShipLoadNames();
560        }
561        if (e.getPropertyName().equals(Track.LOADS_CHANGED_PROPERTY)) {
562            updateLoadNames();
563            updateShipLoadNames();
564        }
565        if (e.getPropertyName().equals(Track.LOAD_OPTIONS_CHANGED_PROPERTY)) {
566            if (_track != null) {
567                updateButtons(true);
568            }
569        }
570    }
571
572    private final static Logger log = LoggerFactory.getLogger(TrackLoadEditFrame.class);
573}