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.add(new ShowCheckboxesCarsTableAction(carsTableModel));
256        toolMenu.add(new ResetCheckboxesCarsTableAction(carsTableModel));
257        toolMenu.add(new ModifyLocationsAction());
258        toolMenu.add(new TrainsByCarTypeAction());
259        toolMenu.add(new PrintCarLoadsAction(false));
260        toolMenu.add(new PrintCarLoadsAction(true));
261        toolMenu.add(new CarsSetFrameAction(carsTable));
262        menuBar.add(toolMenu);
263        menuBar.add(new jmri.jmrit.operations.OperationsMenu());
264        setJMenuBar(menuBar);
265        addHelpMenu("package.jmri.jmrit.operations.Operations_Cars", true); // NOI18N
266
267        initMinimumSize();
268
269        addHorizontalScrollBarKludgeFix(controlPane, controlPanel);
270
271        // create ShutDownTasks
272        createShutDownTask();
273    }
274
275    @Override
276    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
277        log.debug("radio button activated");
278        // clear any sorts by column
279        clearTableSort(carsTable);
280        if (ae.getSource() == sortByNumber) {
281            carsTableModel.setSort(carsTableModel.SORTBY_NUMBER);
282        }
283        if (ae.getSource() == sortByRoad) {
284            carsTableModel.setSort(carsTableModel.SORTBY_ROAD);
285        }
286        if (ae.getSource() == sortByType) {
287            carsTableModel.setSort(carsTableModel.SORTBY_TYPE);
288        }
289        if (ae.getSource() == sortByColor) {
290            carsTableModel.setSort(carsTableModel.SORTBY_COLOR);
291        }
292        if (ae.getSource() == sortByLoad) {
293            carsTableModel.setSort(carsTableModel.SORTBY_LOAD);
294        }
295        if (ae.getSource() == sortByKernel) {
296            carsTableModel.setSort(carsTableModel.SORTBY_KERNEL);
297        }
298        if (ae.getSource() == sortByLocation) {
299            carsTableModel.setSort(carsTableModel.SORTBY_LOCATION);
300        }
301        if (ae.getSource() == sortByDestination) {
302            carsTableModel.setSort(carsTableModel.SORTBY_DESTINATION);
303        }
304        if (ae.getSource() == sortByFinalDestination) {
305            carsTableModel.setSort(carsTableModel.SORTBY_FINALDESTINATION);
306        }
307        if (ae.getSource() == sortByRwe) {
308            carsTableModel.setSort(carsTableModel.SORTBY_RWE);
309        }
310        if (ae.getSource() == sortByRwl) {
311            carsTableModel.setSort(carsTableModel.SORTBY_RWL);
312        }
313        if (ae.getSource() == sortByRoute) {
314            carsTableModel.setSort(carsTableModel.SORTBY_ROUTE);
315        }
316        if (ae.getSource() == sortByDivision) {
317            carsTableModel.setSort(carsTableModel.SORTBY_DIVISION);
318        }
319        if (ae.getSource() == sortByTrain) {
320            carsTableModel.setSort(carsTableModel.SORTBY_TRAIN);
321        }
322        if (ae.getSource() == sortByMoves) {
323            carsTableModel.setSort(carsTableModel.SORTBY_MOVES);
324        }
325        if (ae.getSource() == sortByBuilt) {
326            carsTableModel.setSort(carsTableModel.SORTBY_BUILT);
327        }
328        if (ae.getSource() == sortByOwner) {
329            carsTableModel.setSort(carsTableModel.SORTBY_OWNER);
330        }
331        if (ae.getSource() == sortByValue) {
332            carsTableModel.setSort(carsTableModel.SORTBY_VALUE);
333        }
334        if (ae.getSource() == sortByRfid) {
335            carsTableModel.setSort(carsTableModel.SORTBY_RFID);
336        }
337        if (ae.getSource() == sortByWait) {
338            carsTableModel.setSort(carsTableModel.SORTBY_WAIT);
339        }
340        if (ae.getSource() == sortByPickup) {
341            carsTableModel.setSort(carsTableModel.SORTBY_PICKUP);
342        }
343        if (ae.getSource() == sortByLast) {
344            carsTableModel.setSort(carsTableModel.SORTBY_LAST);
345        }
346        if (ae.getSource() == sortByComment) {
347            carsTableModel.setSort(carsTableModel.SORTBY_COMMENT);
348        }
349    }
350
351    public List<Car> getSortByList() {
352        return carsTableModel.carList;
353    }
354
355    CarEditFrame f = null;
356
357    // add, find or save button
358    @Override
359    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
360        // log.debug("car button activated");
361        if (ae.getSource() == findButton) {
362            int rowindex = carsTableModel.findCarByRoadNumber(findCarTextBox.getText());
363            if (rowindex < 0) {
364                JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carWithRoadNumNotFound",
365                        findCarTextBox.getText()), Bundle.getMessage("carCouldNotFind"),
366                        JmriJOptionPane.INFORMATION_MESSAGE);
367                return;
368            }
369            // clear any sorts by column
370            clearTableSort(carsTable);
371            carsTable.changeSelection(rowindex, 0, false, false);
372            return;
373        }
374        if (ae.getSource() == addButton) {
375            if (f != null) {
376                f.dispose();
377            }
378            f = new CarEditFrame();
379            f.initComponents(); // default is add car
380        }
381        if (ae.getSource() == saveButton) {
382            if (carsTable.isEditing()) {
383                log.debug("cars table edit true");
384                carsTable.getCellEditor().stopCellEditing();
385            }
386            OperationsXml.save();
387            if (Setup.isCloseWindowOnSaveEnabled()) {
388                dispose();
389            }
390        }
391    }
392
393    protected int[] getCurrentTableColumnWidths() {
394        TableColumnModel tcm = carsTable.getColumnModel();
395        int[] widths = new int[tcm.getColumnCount()];
396        for (int i = 0; i < tcm.getColumnCount(); i++) {
397            widths[i] = tcm.getColumn(i).getWidth();
398        }
399        return widths;
400    }
401
402    @Override
403    public void dispose() {
404        carsTableModel.removeTableModelListener(this);
405        carsTableModel.dispose();
406        if (f != null) {
407            f.dispose();
408        }
409        InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> {
410            tpm.stopPersisting(carsTable);
411        });
412        super.dispose();
413    }
414
415    @Override
416    public void tableChanged(TableModelEvent e) {
417        if (Control.SHOW_PROPERTY) {
418            log.debug("Table changed");
419        }
420        updateNumCars();
421    }
422
423    private void updateNumCars() {
424        String totalNumber = Integer.toString(InstanceManager.getDefault(CarManager.class).getNumEntries());
425        if (showAllCars) {
426            numCars.setText(totalNumber);
427            return;
428        }
429        String showNumber = Integer.toString(getSortByList().size());
430        numCars.setText(showNumber + "/" + totalNumber);
431    }
432
433    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarsTableFrame.class);
434
435}