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