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