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