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.*; 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, 2025 024 */ 025public class EnginesTableFrame extends OperationsFrame implements PropertyChangeListener { 026 027 public EnginesTableModel enginesTableModel; 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 enginesTableModel = new EnginesTableModel(); 070 enginesTable = new JTable(enginesTableModel); 071 enginesPane = new JScrollPane(enginesTable); 072 enginesPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 073 enginesTableModel.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.addSeparator(); 193 toolMenu.add(new ShowCheckboxesEnginesTableAction(enginesTableModel)); 194 toolMenu.add(new ResetCheckboxesEnginesTableAction(enginesTableModel)); 195 toolMenu.addSeparator(); 196 toolMenu.add(new EnginesSetFrameAction(enginesTable)); 197 toolMenu.add(new NceConsistEngineAction()); 198 menuBar.add(toolMenu); 199 menuBar.add(new jmri.jmrit.operations.OperationsMenu()); 200 setJMenuBar(menuBar); 201 addHelpMenu("package.jmri.jmrit.operations.Operations_Locomotives", true); // NOI18N 202 203 initMinimumSize(); 204 205 addHorizontalScrollBarKludgeFix(controlPane, controlPanel); 206 207 // create ShutDownTasks 208 createShutDownTask(); 209 } 210 211 @Override 212 public void radioButtonActionPerformed(java.awt.event.ActionEvent ae) { 213 log.debug("radio button activated"); 214 // clear any sorts by column 215 clearTableSort(enginesTable); 216 if (ae.getSource() == sortByNumber) { 217 enginesTableModel.setSort(enginesTableModel.SORTBY_NUMBER); 218 } 219 if (ae.getSource() == sortByRoad) { 220 enginesTableModel.setSort(enginesTableModel.SORTBY_ROAD); 221 } 222 if (ae.getSource() == sortByModel) { 223 enginesTableModel.setSort(enginesTableModel.SORTBY_MODEL); 224 } 225 if (ae.getSource() == sortByConsist) { 226 enginesTableModel.setSort(enginesTableModel.SORTBY_CONSIST); 227 } 228 if (ae.getSource() == sortByLocation) { 229 enginesTableModel.setSort(enginesTableModel.SORTBY_LOCATION); 230 } 231 if (ae.getSource() == sortByDestination) { 232 enginesTableModel.setSort(enginesTableModel.SORTBY_DESTINATION); 233 } 234 if (ae.getSource() == sortByTrain) { 235 enginesTableModel.setSort(enginesTableModel.SORTBY_TRAIN); 236 } 237 if (ae.getSource() == sortByMoves) { 238 enginesTableModel.setSort(enginesTableModel.SORTBY_MOVES); 239 } 240 if (ae.getSource() == sortByBuilt) { 241 enginesTableModel.setSort(enginesTableModel.SORTBY_BUILT); 242 } 243 if (ae.getSource() == sortByOwner) { 244 enginesTableModel.setSort(enginesTableModel.SORTBY_OWNER); 245 } 246 if (ae.getSource() == sortByValue) { 247 enginesTableModel.setSort(enginesTableModel.SORTBY_VALUE); 248 } 249 if (ae.getSource() == sortByRfid) { 250 enginesTableModel.setSort(enginesTableModel.SORTBY_RFID); 251 } 252 if (ae.getSource() == sortByLast) { 253 enginesTableModel.setSort(enginesTableModel.SORTBY_LAST); 254 } 255 if (ae.getSource() == sortByDcc) { 256 enginesTableModel.setSort(enginesTableModel.SORTBY_DCC_ADDRESS); 257 } 258 if (ae.getSource() == sortByComment) { 259 enginesTableModel.setSort(enginesTableModel.SORTBY_COMMENT); 260 } 261 } 262 263 public List<Engine> getSortByList() { 264 return enginesTableModel.getSelectedEngineList(); 265 } 266 267 EngineEditFrame engineEditFrame = null; 268 269 // add, save or find button 270 @Override 271 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 272 // log.debug("engine button activated"); 273 if (ae.getSource() == findButton) { 274 int rowindex = enginesTableModel.findEngineByRoadNumber(findEngineTextBox.getText()); 275 if (rowindex < 0) { 276 JmriJOptionPane.showMessageDialog(this, 277 Bundle.getMessage("engineWithRoadNumNotFound", findEngineTextBox.getText()), 278 Bundle.getMessage("engineCouldNotFind"), JmriJOptionPane.INFORMATION_MESSAGE); 279 return; 280 281 } 282 // clear any sorts by column 283 clearTableSort(enginesTable); 284 enginesTable.changeSelection(rowindex, 0, false, false); 285 return; 286 } 287 if (ae.getSource() == addButton) { 288 if (engineEditFrame != null) { 289 engineEditFrame.dispose(); 290 } 291 engineEditFrame = new EngineEditFrame(); 292 engineEditFrame.initComponents(); 293 } 294 if (ae.getSource() == saveButton) { 295 if (enginesTable.isEditing()) { 296 log.debug("locomotives table edit true"); 297 enginesTable.getCellEditor().stopCellEditing(); 298 } 299 OperationsXml.save(); 300 if (Setup.isCloseWindowOnSaveEnabled()) { 301 dispose(); 302 } 303 } 304 } 305 306 protected int[] getCurrentTableColumnWidths() { 307 TableColumnModel tcm = enginesTable.getColumnModel(); 308 int[] widths = new int[tcm.getColumnCount()]; 309 for (int i = 0; i < tcm.getColumnCount(); i++) { 310 widths[i] = tcm.getColumn(i).getWidth(); 311 } 312 return widths; 313 } 314 315 @Override 316 public void dispose() { 317 engineManager.removePropertyChangeListener(this); 318 enginesTableModel.dispose(); 319 if (engineEditFrame != null) { 320 engineEditFrame.dispose(); 321 } 322 InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> { 323 tpm.stopPersisting(enginesTable); 324 }); 325 super.dispose(); 326 } 327 328 @Override 329 public void propertyChange(PropertyChangeEvent e) { 330 if (Control.SHOW_PROPERTY) { 331 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 332 .getNewValue()); 333 } 334 if (e.getPropertyName().equals(EngineManager.LISTLENGTH_CHANGED_PROPERTY)) { 335 numEngines.setText(Integer.toString(engineManager.getNumEntries())); 336 } 337 } 338 339 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EnginesTableFrame.class); 340}