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