001package jmri.jmrit.operations.rollingstock.engines;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.util.List;
006
007import javax.swing.*;
008import javax.swing.table.TableColumnModel;
009
010import jmri.InstanceManager;
011import jmri.jmrit.operations.OperationsFrame;
012import jmri.jmrit.operations.OperationsXml;
013import jmri.jmrit.operations.rollingstock.engines.tools.NceConsistEngineAction;
014import jmri.jmrit.operations.setup.Control;
015import jmri.jmrit.operations.setup.Setup;
016import jmri.swing.JTablePersistenceManager;
017import jmri.util.swing.JmriJOptionPane;
018
019/**
020 * Frame for adding and editing the engine roster for operations.
021 *
022 * @author Bob Jacobsen Copyright (C) 2001
023 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012, 2013
024 */
025public class EnginesTableFrame extends OperationsFrame implements PropertyChangeListener {
026
027    public EnginesTableModel enginesModel;
028    javax.swing.JTable enginesTable;
029    JScrollPane enginesPane;
030    EngineManager engineManager = InstanceManager.getDefault(EngineManager.class);
031
032    // labels
033    JLabel numEngines = new JLabel();
034    JLabel textEngines = new JLabel();
035    JLabel textSep1 = new JLabel("          ");
036
037    // radio buttons
038    JRadioButton sortByNumber = new JRadioButton(Bundle.getMessage("Number"));
039    JRadioButton sortByRoad = new JRadioButton(Bundle.getMessage("Road"));
040    JRadioButton sortByModel = new JRadioButton(Bundle.getMessage("Model"));
041    public JRadioButton sortByConsist = new JRadioButton(Bundle.getMessage("Consist"));
042    JRadioButton sortByLocation = new JRadioButton(Bundle.getMessage("Location"));
043    JRadioButton sortByDestination = new JRadioButton(Bundle.getMessage("Destination"));
044    JRadioButton sortByTrain = new JRadioButton(Bundle.getMessage("Train"));
045    JRadioButton sortByMoves = new JRadioButton(Bundle.getMessage("Moves"));
046    JRadioButton sortByBuilt = new JRadioButton(Bundle.getMessage("Built"));
047    JRadioButton sortByOwner = new JRadioButton(Bundle.getMessage("Owner"));
048    public JRadioButton sortByValue = new JRadioButton(Setup.getValueLabel());
049    public JRadioButton sortByRfid = new JRadioButton(Setup.getRfidLabel());
050    JRadioButton sortByDcc = new JRadioButton(Bundle.getMessage("DccAddress"));
051    JRadioButton sortByLast = new JRadioButton(Bundle.getMessage("Last"));
052    JRadioButton sortByComment = new JRadioButton(Bundle.getMessage("Comment"));
053    ButtonGroup group = new ButtonGroup();
054
055    // major buttons
056    JButton addButton = new JButton(Bundle.getMessage("TitleEngineAdd"));
057    JButton findButton = new JButton(Bundle.getMessage("Find"));
058    JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
059
060    JTextField findEngineTextBox = new JTextField(6);
061
062    public EnginesTableFrame() {
063        super(Bundle.getMessage("TitleEnginesTable"));
064        // general GUI config
065
066        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
067
068        // Set up the jtable in a Scroll Pane..
069        enginesModel = new EnginesTableModel();
070        enginesTable = new JTable(enginesModel);
071        enginesPane = new JScrollPane(enginesTable);
072        enginesPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
073        enginesModel.initTable(enginesTable, this);
074
075        // load the number of engines and listen for changes
076        numEngines.setText(Integer.toString(engineManager.getNumEntries()));
077        engineManager.addPropertyChangeListener(this);
078        textEngines.setText(Bundle.getMessage("engines"));
079
080        // Set up the control panel
081        // row 1
082        JPanel cp1 = new JPanel();
083        cp1.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy")));
084
085        cp1.add(sortByNumber);
086        cp1.add(sortByRoad);
087        cp1.add(sortByModel);
088        cp1.add(sortByConsist);
089        cp1.add(sortByLocation);
090        cp1.add(sortByDestination);
091        cp1.add(sortByTrain);
092        JPanel movep = new JPanel();
093        movep.setBorder(BorderFactory.createTitledBorder(""));
094        movep.add(sortByMoves);
095        movep.add(sortByBuilt);
096        movep.add(sortByOwner);
097        if (Setup.isValueEnabled()) {
098            movep.add(sortByValue);
099        }
100        if (Setup.isRfidEnabled()) {
101            movep.add(sortByRfid);
102        }
103        movep.add(sortByDcc);
104        movep.add(sortByLast);
105        movep.add(sortByComment);
106        cp1.add(movep);
107
108        // row 2
109        JPanel cp2 = new JPanel();
110        cp2.setLayout(new BoxLayout(cp2, BoxLayout.X_AXIS));
111
112        JPanel cp2Add = new JPanel();
113        cp2Add.setBorder(BorderFactory.createTitledBorder(""));
114        addButton.setToolTipText(Bundle.getMessage("TipAddButton"));
115        cp2Add.add(numEngines);
116        cp2Add.add(textEngines);
117        cp2Add.add(textSep1);
118        cp2Add.add(addButton);
119        cp2.add(cp2Add);
120
121        JPanel cp2Find = new JPanel();
122        cp2Find.setBorder(BorderFactory.createTitledBorder(""));
123        findButton.setToolTipText(Bundle.getMessage("findEngine"));
124        findEngineTextBox.setToolTipText(Bundle.getMessage("findEngine"));
125        cp2Find.add(findButton);
126        cp2Find.add(findEngineTextBox);
127        cp2.add(cp2Find);
128
129        JPanel cp2Save = new JPanel();
130        cp2Save.setBorder(BorderFactory.createTitledBorder(""));
131        cp2Save.add(saveButton);
132        cp2.add(cp2Save);
133
134        // place controls in scroll pane
135        JPanel controlPanel = new JPanel();
136        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
137        controlPanel.add(cp1);
138        controlPanel.add(cp2);
139
140        // some tool tips
141        sortByLast.setToolTipText(Bundle.getMessage("TipLastMoved"));
142
143        JScrollPane controlPane = new JScrollPane(controlPanel);
144
145        getContentPane().add(enginesPane);
146        getContentPane().add(controlPane);
147
148        // setup buttons
149        addButtonAction(addButton);
150        addButtonAction(findButton);
151        addButtonAction(saveButton);
152
153        sortByNumber.setSelected(true);
154        addRadioButtonAction(sortByNumber);
155        addRadioButtonAction(sortByRoad);
156        addRadioButtonAction(sortByModel);
157        addRadioButtonAction(sortByConsist);
158        addRadioButtonAction(sortByLocation);
159        addRadioButtonAction(sortByDestination);
160        addRadioButtonAction(sortByTrain);
161        addRadioButtonAction(sortByMoves);
162        addRadioButtonAction(sortByBuilt);
163        addRadioButtonAction(sortByOwner);
164        addRadioButtonAction(sortByValue);
165        addRadioButtonAction(sortByRfid);
166        addRadioButtonAction(sortByDcc);
167        addRadioButtonAction(sortByLast);
168        addRadioButtonAction(sortByComment);
169
170        group.add(sortByNumber);
171        group.add(sortByRoad);
172        group.add(sortByModel);
173        group.add(sortByConsist);
174        group.add(sortByLocation);
175        group.add(sortByDestination);
176        group.add(sortByTrain);
177        group.add(sortByMoves);
178        group.add(sortByBuilt);
179        group.add(sortByOwner);
180        group.add(sortByValue);
181        group.add(sortByRfid);
182        group.add(sortByDcc);
183        group.add(sortByLast);
184        group.add(sortByComment);
185        
186        sortByDcc.setToolTipText(Bundle.getMessage("TipDccAddressFromRoster"));
187
188        // build menu
189        JMenuBar menuBar = new JMenuBar();
190        JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools"));
191        toolMenu.add(new EngineRosterMenu(Bundle.getMessage("TitleEngineRoster"), EngineRosterMenu.MAINMENU, this));
192        toolMenu.add(new NceConsistEngineAction());
193        menuBar.add(toolMenu);
194        menuBar.add(new jmri.jmrit.operations.OperationsMenu());
195        setJMenuBar(menuBar);
196        addHelpMenu("package.jmri.jmrit.operations.Operations_Locomotives", true); // NOI18N
197
198        initMinimumSize();
199
200        addHorizontalScrollBarKludgeFix(controlPane, controlPanel);
201
202        // create ShutDownTasks
203        createShutDownTask();
204    }
205
206    @Override
207    public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) {
208        log.debug("radio button activated");
209        // clear any sorts by column
210        clearTableSort(enginesTable);
211        if (ae.getSource() == sortByNumber) {
212            enginesModel.setSort(enginesModel.SORTBY_NUMBER);
213        }
214        if (ae.getSource() == sortByRoad) {
215            enginesModel.setSort(enginesModel.SORTBY_ROAD);
216        }
217        if (ae.getSource() == sortByModel) {
218            enginesModel.setSort(enginesModel.SORTBY_MODEL);
219        }
220        if (ae.getSource() == sortByConsist) {
221            enginesModel.setSort(enginesModel.SORTBY_CONSIST);
222        }
223        if (ae.getSource() == sortByLocation) {
224            enginesModel.setSort(enginesModel.SORTBY_LOCATION);
225        }
226        if (ae.getSource() == sortByDestination) {
227            enginesModel.setSort(enginesModel.SORTBY_DESTINATION);
228        }
229        if (ae.getSource() == sortByTrain) {
230            enginesModel.setSort(enginesModel.SORTBY_TRAIN);
231        }
232        if (ae.getSource() == sortByMoves) {
233            enginesModel.setSort(enginesModel.SORTBY_MOVES);
234        }
235        if (ae.getSource() == sortByBuilt) {
236            enginesModel.setSort(enginesModel.SORTBY_BUILT);
237        }
238        if (ae.getSource() == sortByOwner) {
239            enginesModel.setSort(enginesModel.SORTBY_OWNER);
240        }
241        if (ae.getSource() == sortByValue) {
242            enginesModel.setSort(enginesModel.SORTBY_VALUE);
243        }
244        if (ae.getSource() == sortByRfid) {
245            enginesModel.setSort(enginesModel.SORTBY_RFID);
246        }
247        if (ae.getSource() == sortByLast) {
248            enginesModel.setSort(enginesModel.SORTBY_LAST);
249        }
250        if (ae.getSource() == sortByDcc) {
251            enginesModel.setSort(enginesModel.SORTBY_DCC_ADDRESS);
252        }
253        if (ae.getSource() == sortByComment) {
254            enginesModel.setSort(enginesModel.SORTBY_COMMENT);
255        }
256    }
257
258    public List<Engine> getSortByList() {
259        return enginesModel.getSelectedEngineList();
260    }
261
262    EngineEditFrame engineEditFrame = null;
263
264    // add, save or find button
265    @Override
266    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
267        // log.debug("engine button activated");
268        if (ae.getSource() == findButton) {
269            int rowindex = enginesModel.findEngineByRoadNumber(findEngineTextBox.getText());
270            if (rowindex < 0) {
271                JmriJOptionPane.showMessageDialog(this, 
272                        Bundle.getMessage("engineWithRoadNumNotFound", findEngineTextBox.getText()),
273                        Bundle.getMessage("engineCouldNotFind"), JmriJOptionPane.INFORMATION_MESSAGE);
274                return;
275
276            }
277            // clear any sorts by column
278            clearTableSort(enginesTable);
279            enginesTable.changeSelection(rowindex, 0, false, false);
280            return;
281        }
282        if (ae.getSource() == addButton) {
283            if (engineEditFrame != null) {
284                engineEditFrame.dispose();
285            }
286            engineEditFrame = new EngineEditFrame();
287            engineEditFrame.initComponents();
288        }
289        if (ae.getSource() == saveButton) {
290            if (enginesTable.isEditing()) {
291                log.debug("locomotives table edit true");
292                enginesTable.getCellEditor().stopCellEditing();
293            }
294            OperationsXml.save();
295            if (Setup.isCloseWindowOnSaveEnabled()) {
296                dispose();
297            }
298        }
299    }
300
301    protected int[] getCurrentTableColumnWidths() {
302        TableColumnModel tcm = enginesTable.getColumnModel();
303        int[] widths = new int[tcm.getColumnCount()];
304        for (int i = 0; i < tcm.getColumnCount(); i++) {
305            widths[i] = tcm.getColumn(i).getWidth();
306        }
307        return widths;
308    }
309
310    @Override
311    public void dispose() {
312        engineManager.removePropertyChangeListener(this);
313        enginesModel.dispose();
314        if (engineEditFrame != null) {
315            engineEditFrame.dispose();
316        }
317        InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> {
318            tpm.stopPersisting(enginesTable);
319        });
320        super.dispose();
321    }
322
323    @Override
324    public void propertyChange(PropertyChangeEvent e) {
325        if (Control.SHOW_PROPERTY) {
326            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
327                    .getNewValue());
328        }
329        if (e.getPropertyName().equals(EngineManager.LISTLENGTH_CHANGED_PROPERTY)) {
330            numEngines.setText(Integer.toString(engineManager.getNumEntries()));
331        }
332    }
333
334    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EnginesTableFrame.class);
335}