001package jmri.jmrit.operations.rollingstock.cars;
002
003import java.util.List;
004
005import javax.swing.*;
006import javax.swing.event.TableModelEvent;
007import javax.swing.event.TableModelListener;
008import javax.swing.table.TableColumnModel;
009
010import jmri.InstanceManager;
011import jmri.jmrit.operations.OperationsFrame;
012import jmri.jmrit.operations.OperationsXml;
013import jmri.jmrit.operations.locations.schedules.ScheduleManager;
014import jmri.jmrit.operations.locations.tools.ModifyLocationsAction;
015import jmri.jmrit.operations.rollingstock.cars.tools.*;
016import jmri.jmrit.operations.setup.Control;
017import jmri.jmrit.operations.setup.Setup;
018import jmri.jmrit.operations.trains.tools.TrainsByCarTypeAction;
019import jmri.swing.JTablePersistenceManager;
020import jmri.util.swing.JmriJOptionPane;
021
022/**
023 * Frame for adding and editing the car roster for operations.
024 *
025 * @author Bob Jacobsen Copyright (C) 2001
026 * @author Daniel Boudreau Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013,
027 * 2014
028 */
029public class CarsTableFrame extends OperationsFrame implements TableModelListener {
030
031    public CarsTableModel carsTableModel;
032    public JTable carsTable;
033    boolean showAllCars;
034    String locationName;
035    String trackName;
036    CarManager carManager = InstanceManager.getDefault(CarManager.class);
037
038    // labels
039    JLabel numCars = new JLabel();
040    JLabel textCars = new JLabel(Bundle.getMessage("cars"));
041    JLabel textSep1 = new JLabel("      ");
042
043    // radio buttons
044    JRadioButton sortByNumber = new JRadioButton(Bundle.getMessage("Number"));
045    JRadioButton sortByRoad = new JRadioButton(Bundle.getMessage("Road"));
046    JRadioButton sortByType = new JRadioButton(Bundle.getMessage("Type"));
047    JRadioButton sortByColor = new JRadioButton(Bundle.getMessage("Color"));
048    JRadioButton sortByLoad = new JRadioButton(Bundle.getMessage("Load"));
049    JRadioButton sortByKernel = new JRadioButton(Bundle.getMessage("Kernel"));
050    JRadioButton sortByLocation = new JRadioButton(Bundle.getMessage("Location"));
051    JRadioButton sortByDestination = new JRadioButton(Bundle.getMessage("Destination"));
052    JRadioButton sortByFinalDestination = new JRadioButton(Bundle.getMessage("FD"));
053    JRadioButton sortByRwe = new JRadioButton(Bundle.getMessage("RWE"));
054    JRadioButton sortByRwl = new JRadioButton(Bundle.getMessage("RWL"));
055    JRadioButton sortByRoute = new JRadioButton(Bundle.getMessage("Route"));
056    JRadioButton sortByDivision = new JRadioButton(Bundle.getMessage("Division"));
057    JRadioButton sortByTrain = new JRadioButton(Bundle.getMessage("Train"));
058    JRadioButton sortByMoves = new JRadioButton(Bundle.getMessage("Moves"));
059    JRadioButton sortByBuilt = new JRadioButton(Bundle.getMessage("Built"));
060    JRadioButton sortByOwner = new JRadioButton(Bundle.getMessage("Owner"));
061    JRadioButton sortByValue = new JRadioButton(Setup.getValueLabel());
062    JRadioButton sortByRfid = new JRadioButton(Setup.getRfidLabel());
063    JRadioButton sortByWait = new JRadioButton(Bundle.getMessage("Wait"));
064    JRadioButton sortByPickup = new JRadioButton(Bundle.getMessage("Pickup"));
065    JRadioButton sortByLast = new JRadioButton(Bundle.getMessage("Last"));
066    JRadioButton sortByComment = new JRadioButton(Bundle.getMessage("Comment"));
067    ButtonGroup group = new ButtonGroup();
068
069    // major buttons
070    JButton addButton = new JButton(Bundle.getMessage("TitleCarAdd"));
071    JButton findButton = new JButton(Bundle.getMessage("Find"));
072    JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
073
074    JTextField findCarTextBox = new JTextField(6);
075
076    public CarsTableFrame(boolean showAllCars, String locationName, String trackName) {
077        super(Bundle.getMessage("TitleCarsTable"));
078        this.showAllCars = showAllCars;
079        this.locationName = locationName;
080        this.trackName = trackName;
081        // general GUI configuration
082        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
083
084        // Set up the table in a Scroll Pane..
085        carsTableModel = new CarsTableModel(showAllCars, locationName, trackName);
086        carsTable = new JTable(carsTableModel);
087        JScrollPane carsPane = new JScrollPane(carsTable);
088        carsPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
089        carsTableModel.initTable(carsTable, this);
090
091        // load the number of cars and listen for changes
092        updateNumCars();
093        carsTableModel.addTableModelListener(this);
094
095        // Set up the control panel
096        // row 1
097        JPanel cp1 = new JPanel();
098        cp1.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy")));
099        cp1.add(sortByNumber);
100        cp1.add(sortByRoad);
101        cp1.add(sortByType);
102
103        JPanel clp = new JPanel();
104        clp.setBorder(BorderFactory.createTitledBorder(""));  
105        clp.add(sortByLoad);
106        clp.add(sortByColor);
107        cp1.add(clp);
108        cp1.add(sortByKernel);
109        cp1.add(sortByLocation);
110
111        JPanel destp = new JPanel();
112        destp.setBorder(BorderFactory.createTitledBorder(""));
113        destp.add(sortByDestination);
114        destp.add(sortByFinalDestination);
115        destp.add(sortByRwe);
116        destp.add(sortByRwl);
117        destp.add(sortByRoute);
118        cp1.add(destp);
119        cp1.add(sortByDivision);
120        cp1.add(sortByTrain);
121
122        JPanel movep = new JPanel();
123        movep.setBorder(BorderFactory.createTitledBorder(""));
124        movep.add(sortByMoves);
125        movep.add(sortByBuilt);
126        movep.add(sortByOwner);
127        if (Setup.isValueEnabled()) {
128            movep.add(sortByValue);
129        }
130        if (Setup.isRfidEnabled()) {
131            movep.add(sortByRfid);
132        }
133        if (InstanceManager.getDefault(ScheduleManager.class).numEntries() > 0) {
134            movep.add(sortByWait);
135            movep.add(sortByPickup);
136        }
137        movep.add(sortByLast);
138        movep.add(sortByComment);
139        cp1.add(movep);
140
141        // row 2
142        JPanel cp2 = new JPanel();
143        cp2.setLayout(new BoxLayout(cp2, BoxLayout.X_AXIS));
144
145        JPanel cp2Add = new JPanel();
146        cp2Add.setBorder(BorderFactory.createTitledBorder(""));
147        addButton.setToolTipText(Bundle.getMessage("TipAddButton"));
148        cp2Add.add(numCars);
149        cp2Add.add(textCars);
150        cp2Add.add(textSep1);
151        cp2Add.add(addButton);
152        cp2.add(cp2Add);
153
154        JPanel cp2Find = new JPanel();
155        cp2Find.setBorder(BorderFactory.createTitledBorder(""));
156        findButton.setToolTipText(Bundle.getMessage("findCar"));
157        findCarTextBox.setToolTipText(Bundle.getMessage("findCar"));
158        cp2Find.add(findButton);
159        cp2Find.add(findCarTextBox);
160        cp2.add(cp2Find);
161
162        JPanel cp2Save = new JPanel();
163        cp2Save.setBorder(BorderFactory.createTitledBorder(""));
164        cp2Save.add(saveButton);
165        cp2.add(cp2Save);
166
167        // place controls in scroll pane
168        JPanel controlPanel = new JPanel();
169        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
170        controlPanel.add(cp1);
171        controlPanel.add(cp2);
172
173        // some tool tips
174        sortByFinalDestination.setToolTipText(Bundle.getMessage("FinalDestination"));
175        sortByRwe.setToolTipText(Bundle.getMessage("ReturnWhenEmpty"));
176        sortByRwl.setToolTipText(Bundle.getMessage("ReturnWhenLoaded"));
177        sortByPickup.setToolTipText(Bundle.getMessage("TipPickup"));
178        sortByLast.setToolTipText(Bundle.getMessage("TipLastMoved"));
179
180        JScrollPane controlPane = new JScrollPane(controlPanel);
181
182        getContentPane().add(carsPane);
183        getContentPane().add(controlPane);
184
185        // setup buttons
186        addButtonAction(addButton);
187        addButtonAction(findButton);
188        addButtonAction(saveButton);
189
190        sortByNumber.setSelected(true);
191        addRadioButtonAction(sortByNumber);
192        addRadioButtonAction(sortByRoad);
193        addRadioButtonAction(sortByType);
194        addRadioButtonAction(sortByColor);
195        addRadioButtonAction(sortByLoad);
196        addRadioButtonAction(sortByKernel);
197        addRadioButtonAction(sortByLocation);
198        addRadioButtonAction(sortByDestination);
199        addRadioButtonAction(sortByFinalDestination);
200        addRadioButtonAction(sortByRwe);
201        addRadioButtonAction(sortByRwl);
202        addRadioButtonAction(sortByRoute);
203        addRadioButtonAction(sortByDivision);
204        addRadioButtonAction(sortByTrain);
205        addRadioButtonAction(sortByMoves);
206        addRadioButtonAction(sortByBuilt);
207        addRadioButtonAction(sortByOwner);
208        addRadioButtonAction(sortByValue);
209        addRadioButtonAction(sortByRfid);
210        addRadioButtonAction(sortByWait);
211        addRadioButtonAction(sortByPickup);
212        addRadioButtonAction(sortByLast);
213        addRadioButtonAction(sortByComment);
214
215        group.add(sortByNumber);
216        group.add(sortByRoad);
217        group.add(sortByType);
218        group.add(sortByColor);
219        group.add(sortByLoad);
220        group.add(sortByKernel);
221        group.add(sortByLocation);
222        group.add(sortByDestination);
223        group.add(sortByFinalDestination);
224        group.add(sortByRwe);
225        group.add(sortByRwl);
226        group.add(sortByRoute);
227        group.add(sortByDivision);
228        group.add(sortByTrain);
229        group.add(sortByMoves);
230        group.add(sortByBuilt);
231        group.add(sortByOwner);
232        group.add(sortByValue);
233        group.add(sortByRfid);
234        group.add(sortByWait);
235        group.add(sortByPickup);
236        group.add(sortByLast);
237        group.add(sortByComment);
238
239        // sort by location
240        if (!showAllCars) {
241            sortByLocation.doClick();
242            if (locationName != null) {
243                String title = Bundle.getMessage("TitleCarsTable") + " " + locationName;
244                if (trackName != null) {
245                    title = title + " " + trackName;
246                }
247                setTitle(title);
248            }
249        }
250
251        // build menu
252        JMenuBar menuBar = new JMenuBar();
253        JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
254        toolMenu.add(new CarRosterMenu(Bundle.getMessage("TitleCarRoster"), CarRosterMenu.MAINMENU, this));
255        toolMenu.addSeparator();
256        toolMenu.add(new ShowCheckboxesCarsTableAction(carsTableModel));
257        toolMenu.add(new ResetCheckboxesCarsTableAction(carsTableModel));
258        toolMenu.addSeparator();
259        toolMenu.add(new ModifyLocationsAction());
260        toolMenu.add(new TrainsByCarTypeAction());
261        toolMenu.addSeparator();
262        toolMenu.add(new PrintCarLoadsAction(false));
263        toolMenu.add(new PrintCarLoadsAction(true));
264        toolMenu.addSeparator();
265        toolMenu.add(new CarsSetFrameAction(carsTable));
266        menuBar.add(toolMenu);
267        menuBar.add(new jmri.jmrit.operations.OperationsMenu());
268        setJMenuBar(menuBar);
269        addHelpMenu("package.jmri.jmrit.operations.Operations_Cars", true); // NOI18N
270
271        initMinimumSize();
272
273        addHorizontalScrollBarKludgeFix(controlPane, controlPanel);
274
275        // create ShutDownTasks
276        createShutDownTask();
277    }
278
279    @Override
280    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
281        log.debug("radio button activated");
282        // clear any sorts by column
283        clearTableSort(carsTable);
284        if (ae.getSource() == sortByNumber) {
285            carsTableModel.setSort(carsTableModel.SORTBY_NUMBER);
286        }
287        if (ae.getSource() == sortByRoad) {
288            carsTableModel.setSort(carsTableModel.SORTBY_ROAD);
289        }
290        if (ae.getSource() == sortByType) {
291            carsTableModel.setSort(carsTableModel.SORTBY_TYPE);
292        }
293        if (ae.getSource() == sortByColor) {
294            carsTableModel.setSort(carsTableModel.SORTBY_COLOR);
295        }
296        if (ae.getSource() == sortByLoad) {
297            carsTableModel.setSort(carsTableModel.SORTBY_LOAD);
298        }
299        if (ae.getSource() == sortByKernel) {
300            carsTableModel.setSort(carsTableModel.SORTBY_KERNEL);
301        }
302        if (ae.getSource() == sortByLocation) {
303            carsTableModel.setSort(carsTableModel.SORTBY_LOCATION);
304        }
305        if (ae.getSource() == sortByDestination) {
306            carsTableModel.setSort(carsTableModel.SORTBY_DESTINATION);
307        }
308        if (ae.getSource() == sortByFinalDestination) {
309            carsTableModel.setSort(carsTableModel.SORTBY_FINALDESTINATION);
310        }
311        if (ae.getSource() == sortByRwe) {
312            carsTableModel.setSort(carsTableModel.SORTBY_RWE);
313        }
314        if (ae.getSource() == sortByRwl) {
315            carsTableModel.setSort(carsTableModel.SORTBY_RWL);
316        }
317        if (ae.getSource() == sortByRoute) {
318            carsTableModel.setSort(carsTableModel.SORTBY_ROUTE);
319        }
320        if (ae.getSource() == sortByDivision) {
321            carsTableModel.setSort(carsTableModel.SORTBY_DIVISION);
322        }
323        if (ae.getSource() == sortByTrain) {
324            carsTableModel.setSort(carsTableModel.SORTBY_TRAIN);
325        }
326        if (ae.getSource() == sortByMoves) {
327            carsTableModel.setSort(carsTableModel.SORTBY_MOVES);
328        }
329        if (ae.getSource() == sortByBuilt) {
330            carsTableModel.setSort(carsTableModel.SORTBY_BUILT);
331        }
332        if (ae.getSource() == sortByOwner) {
333            carsTableModel.setSort(carsTableModel.SORTBY_OWNER);
334        }
335        if (ae.getSource() == sortByValue) {
336            carsTableModel.setSort(carsTableModel.SORTBY_VALUE);
337        }
338        if (ae.getSource() == sortByRfid) {
339            carsTableModel.setSort(carsTableModel.SORTBY_RFID);
340        }
341        if (ae.getSource() == sortByWait) {
342            carsTableModel.setSort(carsTableModel.SORTBY_WAIT);
343        }
344        if (ae.getSource() == sortByPickup) {
345            carsTableModel.setSort(carsTableModel.SORTBY_PICKUP);
346        }
347        if (ae.getSource() == sortByLast) {
348            carsTableModel.setSort(carsTableModel.SORTBY_LAST);
349        }
350        if (ae.getSource() == sortByComment) {
351            carsTableModel.setSort(carsTableModel.SORTBY_COMMENT);
352        }
353    }
354
355    public List<Car> getSortByList() {
356        return carsTableModel.carList;
357    }
358
359    CarEditFrame f = null;
360
361    // add, find or save button
362    @Override
363    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
364        // log.debug("car button activated");
365        if (ae.getSource() == findButton) {
366            int rowindex = carsTableModel.findCarByRoadNumber(findCarTextBox.getText());
367            if (rowindex < 0) {
368                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carWithRoadNumNotFound",
369                        findCarTextBox.getText()), Bundle.getMessage("carCouldNotFind"),
370                        JmriJOptionPane.INFORMATION_MESSAGE);
371                return;
372            }
373            // clear any sorts by column
374            clearTableSort(carsTable);
375            carsTable.changeSelection(rowindex, 0, false, false);
376            return;
377        }
378        if (ae.getSource() == addButton) {
379            if (f != null) {
380                f.dispose();
381            }
382            f = new CarEditFrame();
383            f.initComponents(); // default is add car
384        }
385        if (ae.getSource() == saveButton) {
386            if (carsTable.isEditing()) {
387                log.debug("cars table edit true");
388                carsTable.getCellEditor().stopCellEditing();
389            }
390            OperationsXml.save();
391            if (Setup.isCloseWindowOnSaveEnabled()) {
392                dispose();
393            }
394        }
395    }
396
397    protected int[] getCurrentTableColumnWidths() {
398        TableColumnModel tcm = carsTable.getColumnModel();
399        int[] widths = new int[tcm.getColumnCount()];
400        for (int i = 0; i < tcm.getColumnCount(); i++) {
401            widths[i] = tcm.getColumn(i).getWidth();
402        }
403        return widths;
404    }
405
406    @Override
407    public void dispose() {
408        carsTableModel.removeTableModelListener(this);
409        carsTableModel.dispose();
410        if (f != null) {
411            f.dispose();
412        }
413        InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> {
414            tpm.stopPersisting(carsTable);
415        });
416        super.dispose();
417    }
418
419    @Override
420    public void tableChanged(TableModelEvent e) {
421        if (Control.SHOW_PROPERTY) {
422            log.debug("Table changed");
423        }
424        updateNumCars();
425    }
426
427    private void updateNumCars() {
428        String totalNumber = Integer.toString(InstanceManager.getDefault(CarManager.class).getNumEntries());
429        if (showAllCars) {
430            numCars.setText(totalNumber);
431            return;
432        }
433        String showNumber = Integer.toString(getSortByList().size());
434        numCars.setText(showNumber + "/" + totalNumber);
435    }
436
437    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarsTableFrame.class);
438
439}