001package jmri.jmrit.operations.rollingstock.cars.gui; 002 003import java.awt.event.ActionEvent; 004import java.util.List; 005 006import javax.swing.*; 007import javax.swing.event.TableModelEvent; 008import javax.swing.event.TableModelListener; 009import javax.swing.table.TableColumnModel; 010 011import jmri.InstanceManager; 012import jmri.jmrit.operations.OperationsFrame; 013import jmri.jmrit.operations.OperationsXml; 014import jmri.jmrit.operations.locations.schedules.ScheduleManager; 015import jmri.jmrit.operations.locations.tools.ModifyLocationsAction; 016import jmri.jmrit.operations.rollingstock.cars.Car; 017import jmri.jmrit.operations.rollingstock.cars.CarManager; 018import jmri.jmrit.operations.rollingstock.cars.tools.*; 019import jmri.jmrit.operations.setup.Control; 020import jmri.jmrit.operations.setup.Setup; 021import jmri.jmrit.operations.trains.tools.TrainsByCarTypeAction; 022import jmri.swing.JTablePersistenceManager; 023import jmri.util.swing.JmriJOptionPane; 024 025/** 026 * Frame for adding and editing the car roster for operations. 027 * 028 * @author Bob Jacobsen Copyright (C) 2001 029 * @author Daniel Boudreau Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 030 * 2014, 2025 031 */ 032public class CarsTableFrame extends OperationsFrame implements TableModelListener { 033 034 public CarsTableModel carsTableModel; 035 public JTable carsTable; 036 boolean showAllCars; 037 CarManager carManager = InstanceManager.getDefault(CarManager.class); 038 039 // labels 040 JLabel numCars = new JLabel(); 041 JLabel textCars = new JLabel(Bundle.getMessage("cars")); 042 JLabel textSep1 = new JLabel(" "); 043 044 // radio buttons 045 JRadioButton sortByNumber = new JRadioButton(Bundle.getMessage("Number")); 046 JRadioButton sortByRoad = new JRadioButton(Bundle.getMessage("Road")); 047 JRadioButton sortByType = new JRadioButton(Bundle.getMessage("Type")); 048 JRadioButton sortByColor = new JRadioButton(Bundle.getMessage("Color")); 049 JRadioButton sortByLoad = new JRadioButton(Bundle.getMessage("Load")); 050 JRadioButton sortByKernel = new JRadioButton(Bundle.getMessage("Kernel")); 051 JRadioButton sortByLocation = new JRadioButton(Bundle.getMessage("Location")); 052 JRadioButton sortByDestination = new JRadioButton(Bundle.getMessage("Destination")); 053 JRadioButton sortByFinalDestination = new JRadioButton(Bundle.getMessage("FD")); 054 JRadioButton sortByRwe = new JRadioButton(Bundle.getMessage("RWE")); 055 JRadioButton sortByRwl = new JRadioButton(Bundle.getMessage("RWL")); 056 JRadioButton sortByRoute = new JRadioButton(Bundle.getMessage("Route")); 057 JRadioButton sortByDivision = new JRadioButton(Bundle.getMessage("Division")); 058 JRadioButton sortByTrain = new JRadioButton(Bundle.getMessage("Train")); 059 JRadioButton sortByMoves = new JRadioButton(Bundle.getMessage("Moves")); 060 JRadioButton sortByBuilt = new JRadioButton(Bundle.getMessage("Built")); 061 JRadioButton sortByOwner = new JRadioButton(Bundle.getMessage("Owner")); 062 JRadioButton sortByValue = new JRadioButton(Setup.getValueLabel()); 063 JRadioButton sortByRfid = new JRadioButton(Setup.getRfidLabel()); 064 JRadioButton sortByWait = new JRadioButton(Bundle.getMessage("Wait")); 065 JRadioButton sortByPickup = new JRadioButton(Bundle.getMessage("Pickup")); 066 JRadioButton sortByLast = new JRadioButton(Bundle.getMessage("Last")); 067 JRadioButton sortByComment = new JRadioButton(Bundle.getMessage("Comment")); 068 ButtonGroup group = new ButtonGroup(); 069 070 // major buttons 071 JButton addButton = new JButton(Bundle.getMessage("TitleCarAdd")); 072 JButton findButton = new JButton(Bundle.getMessage("Find")); 073 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 074 075 JTextField findCarTextBox = new JTextField(6); 076 077 public CarsTableFrame(boolean showAllCars, String locationName, String trackName) { 078 super(Bundle.getMessage("TitleCarsTable")); 079 this.showAllCars = showAllCars; 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 destp.add(sortByRoute); 117 cp1.add(destp); 118 cp1.add(sortByDivision); 119 cp1.add(sortByTrain); 120 121 JPanel movep = new JPanel(); 122 movep.setBorder(BorderFactory.createTitledBorder("")); 123 movep.add(sortByMoves); 124 movep.add(sortByBuilt); 125 movep.add(sortByOwner); 126 if (Setup.isValueEnabled()) { 127 movep.add(sortByValue); 128 } 129 if (Setup.isRfidEnabled()) { 130 movep.add(sortByRfid); 131 } 132 if (InstanceManager.getDefault(ScheduleManager.class).numEntries() > 0) { 133 movep.add(sortByWait); 134 movep.add(sortByPickup); 135 } 136 movep.add(sortByLast); 137 movep.add(sortByComment); 138 cp1.add(movep); 139 140 // row 2 141 JPanel cp2 = new JPanel(); 142 cp2.setLayout(new BoxLayout(cp2, BoxLayout.X_AXIS)); 143 144 JPanel cp2Add = new JPanel(); 145 cp2Add.setBorder(BorderFactory.createTitledBorder("")); 146 addButton.setToolTipText(Bundle.getMessage("TipAddButton")); 147 cp2Add.add(numCars); 148 cp2Add.add(textCars); 149 cp2Add.add(textSep1); 150 cp2Add.add(addButton); 151 cp2.add(cp2Add); 152 153 JPanel cp2Find = new JPanel(); 154 cp2Find.setBorder(BorderFactory.createTitledBorder("")); 155 findButton.setToolTipText(Bundle.getMessage("findCar")); 156 findCarTextBox.setToolTipText(Bundle.getMessage("findCar")); 157 cp2Find.add(findButton); 158 cp2Find.add(findCarTextBox); 159 cp2.add(cp2Find); 160 161 JPanel cp2Save = new JPanel(); 162 cp2Save.setBorder(BorderFactory.createTitledBorder("")); 163 cp2Save.add(saveButton); 164 cp2.add(cp2Save); 165 166 // place controls in scroll pane 167 JPanel controlPanel = new JPanel(); 168 controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS)); 169 controlPanel.add(cp1); 170 controlPanel.add(cp2); 171 172 // some tool tips 173 sortByFinalDestination.setToolTipText(Bundle.getMessage("FinalDestination")); 174 sortByRwe.setToolTipText(Bundle.getMessage("ReturnWhenEmpty")); 175 sortByRwl.setToolTipText(Bundle.getMessage("ReturnWhenLoaded")); 176 sortByPickup.setToolTipText(Bundle.getMessage("TipPickup")); 177 sortByLast.setToolTipText(Bundle.getMessage("TipLastMoved")); 178 179 JScrollPane controlPane = new JScrollPane(controlPanel); 180 181 getContentPane().add(carsPane); 182 getContentPane().add(controlPane); 183 184 // setup buttons 185 addButtonAction(addButton); 186 addButtonAction(findButton); 187 addButtonAction(saveButton); 188 189 sortByNumber.setSelected(true); 190 addRadioButtonAction(sortByNumber); 191 addRadioButtonAction(sortByRoad); 192 addRadioButtonAction(sortByType); 193 addRadioButtonAction(sortByColor); 194 addRadioButtonAction(sortByLoad); 195 addRadioButtonAction(sortByKernel); 196 addRadioButtonAction(sortByLocation); 197 addRadioButtonAction(sortByDestination); 198 addRadioButtonAction(sortByFinalDestination); 199 addRadioButtonAction(sortByRwe); 200 addRadioButtonAction(sortByRwl); 201 addRadioButtonAction(sortByRoute); 202 addRadioButtonAction(sortByDivision); 203 addRadioButtonAction(sortByTrain); 204 addRadioButtonAction(sortByMoves); 205 addRadioButtonAction(sortByBuilt); 206 addRadioButtonAction(sortByOwner); 207 addRadioButtonAction(sortByValue); 208 addRadioButtonAction(sortByRfid); 209 addRadioButtonAction(sortByWait); 210 addRadioButtonAction(sortByPickup); 211 addRadioButtonAction(sortByLast); 212 addRadioButtonAction(sortByComment); 213 214 findCarTextBox.addActionListener(this::textBoxActionPerformed); 215 216 group.add(sortByNumber); 217 group.add(sortByRoad); 218 group.add(sortByType); 219 group.add(sortByColor); 220 group.add(sortByLoad); 221 group.add(sortByKernel); 222 group.add(sortByLocation); 223 group.add(sortByDestination); 224 group.add(sortByFinalDestination); 225 group.add(sortByRwe); 226 group.add(sortByRwl); 227 group.add(sortByRoute); 228 group.add(sortByDivision); 229 group.add(sortByTrain); 230 group.add(sortByMoves); 231 group.add(sortByBuilt); 232 group.add(sortByOwner); 233 group.add(sortByValue); 234 group.add(sortByRfid); 235 group.add(sortByWait); 236 group.add(sortByPickup); 237 group.add(sortByLast); 238 group.add(sortByComment); 239 240 // sort by location 241 if (!showAllCars) { 242 sortByLocation.doClick(); 243 if (locationName != null) { 244 String title = Bundle.getMessage("TitleCarsTable") + " " + locationName; 245 if (trackName != null) { 246 title = title + " " + trackName; 247 } 248 setTitle(title); 249 } 250 } 251 252 // build menu 253 JMenuBar menuBar = new JMenuBar(); 254 JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools")); 255 toolMenu.add(new CarRosterMenu(Bundle.getMessage("TitleCarRoster"), CarRosterMenu.MAINMENU, this)); 256 toolMenu.addSeparator(); 257 toolMenu.add(new ShowCheckboxesCarsTableAction(carsTableModel)); 258 toolMenu.add(new ResetCheckboxesCarsTableAction(carsTableModel)); 259 toolMenu.addSeparator(); 260 toolMenu.add(new ModifyLocationsAction()); 261 toolMenu.add(new TrainsByCarTypeAction()); 262 toolMenu.addSeparator(); 263 toolMenu.add(new PrintCarLoadsAction(false)); 264 toolMenu.add(new PrintCarLoadsAction(true)); 265 toolMenu.addSeparator(); 266 toolMenu.add(new CarsSetFrameAction(carsTable)); 267 menuBar.add(toolMenu); 268 menuBar.add(new jmri.jmrit.operations.OperationsMenu()); 269 setJMenuBar(menuBar); 270 addHelpMenu("package.jmri.jmrit.operations.Operations_Cars", true); // NOI18N 271 272 initMinimumSize(); 273 274 addHorizontalScrollBarKludgeFix(controlPane, controlPanel); 275 276 // create ShutDownTasks 277 createShutDownTask(); 278 } 279 280 @Override 281 public void radioButtonActionPerformed(ActionEvent ae) { 282 log.debug("radio button activated"); 283 // clear any sorts by column 284 clearTableSort(carsTable); 285 if (ae.getSource() == sortByNumber) { 286 carsTableModel.setSort(carsTableModel.SORTBY_NUMBER); 287 } 288 if (ae.getSource() == sortByRoad) { 289 carsTableModel.setSort(carsTableModel.SORTBY_ROAD); 290 } 291 if (ae.getSource() == sortByType) { 292 carsTableModel.setSort(carsTableModel.SORTBY_TYPE); 293 } 294 if (ae.getSource() == sortByColor) { 295 carsTableModel.setSort(carsTableModel.SORTBY_COLOR); 296 } 297 if (ae.getSource() == sortByLoad) { 298 carsTableModel.setSort(carsTableModel.SORTBY_LOAD); 299 } 300 if (ae.getSource() == sortByKernel) { 301 carsTableModel.setSort(carsTableModel.SORTBY_KERNEL); 302 } 303 if (ae.getSource() == sortByLocation) { 304 carsTableModel.setSort(carsTableModel.SORTBY_LOCATION); 305 } 306 if (ae.getSource() == sortByDestination) { 307 carsTableModel.setSort(carsTableModel.SORTBY_DESTINATION); 308 } 309 if (ae.getSource() == sortByFinalDestination) { 310 carsTableModel.setSort(carsTableModel.SORTBY_FINALDESTINATION); 311 } 312 if (ae.getSource() == sortByRwe) { 313 carsTableModel.setSort(carsTableModel.SORTBY_RWE); 314 } 315 if (ae.getSource() == sortByRwl) { 316 carsTableModel.setSort(carsTableModel.SORTBY_RWL); 317 } 318 if (ae.getSource() == sortByRoute) { 319 carsTableModel.setSort(carsTableModel.SORTBY_ROUTE); 320 } 321 if (ae.getSource() == sortByDivision) { 322 carsTableModel.setSort(carsTableModel.SORTBY_DIVISION); 323 } 324 if (ae.getSource() == sortByTrain) { 325 carsTableModel.setSort(carsTableModel.SORTBY_TRAIN); 326 } 327 if (ae.getSource() == sortByMoves) { 328 carsTableModel.setSort(carsTableModel.SORTBY_MOVES); 329 } 330 if (ae.getSource() == sortByBuilt) { 331 carsTableModel.setSort(carsTableModel.SORTBY_BUILT); 332 } 333 if (ae.getSource() == sortByOwner) { 334 carsTableModel.setSort(carsTableModel.SORTBY_OWNER); 335 } 336 if (ae.getSource() == sortByValue) { 337 carsTableModel.setSort(carsTableModel.SORTBY_VALUE); 338 } 339 if (ae.getSource() == sortByRfid) { 340 carsTableModel.setSort(carsTableModel.SORTBY_RFID); 341 } 342 if (ae.getSource() == sortByWait) { 343 carsTableModel.setSort(carsTableModel.SORTBY_WAIT); 344 } 345 if (ae.getSource() == sortByPickup) { 346 carsTableModel.setSort(carsTableModel.SORTBY_PICKUP); 347 } 348 if (ae.getSource() == sortByLast) { 349 carsTableModel.setSort(carsTableModel.SORTBY_LAST); 350 } 351 if (ae.getSource() == sortByComment) { 352 carsTableModel.setSort(carsTableModel.SORTBY_COMMENT); 353 } 354 } 355 356 public List<Car> getSortByList() { 357 return carsTableModel.carList; 358 } 359 360 CarEditFrame f = null; 361 362 // add, find or save button 363 @Override 364 public void buttonActionPerformed(ActionEvent ae) { 365 // log.debug("car button activated"); 366 if (ae.getSource() == findButton) { 367 findCar(); 368 return; 369 } 370 if (ae.getSource() == addButton) { 371 if (f != null) { 372 f.dispose(); 373 } 374 f = new CarEditFrame(); 375 f.initComponents(); // default is add car 376 } 377 if (ae.getSource() == saveButton) { 378 if (carsTable.isEditing()) { 379 log.debug("cars table edit true"); 380 carsTable.getCellEditor().stopCellEditing(); 381 } 382 OperationsXml.save(); 383 if (Setup.isCloseWindowOnSaveEnabled()) { 384 dispose(); 385 } 386 } 387 } 388 389 public void textBoxActionPerformed(ActionEvent ae) { 390 findCar(); 391 } 392 393 private void findCar() { 394 int rowindex = carsTableModel.findCarByRoadNumber(findCarTextBox.getText()); 395 if (rowindex < 0) { 396 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("carWithRoadNumNotFound", 397 findCarTextBox.getText()), Bundle.getMessage("carCouldNotFind"), 398 JmriJOptionPane.INFORMATION_MESSAGE); 399 return; 400 } 401 // clear any sorts by column 402 clearTableSort(carsTable); 403 carsTable.changeSelection(rowindex, 0, false, false); 404 } 405 406 protected int[] getCurrentTableColumnWidths() { 407 TableColumnModel tcm = carsTable.getColumnModel(); 408 int[] widths = new int[tcm.getColumnCount()]; 409 for (int i = 0; i < tcm.getColumnCount(); i++) { 410 widths[i] = tcm.getColumn(i).getWidth(); 411 } 412 return widths; 413 } 414 415 @Override 416 public void dispose() { 417 carsTableModel.removeTableModelListener(this); 418 carsTableModel.dispose(); 419 if (f != null) { 420 f.dispose(); 421 } 422 InstanceManager.getOptionalDefault(JTablePersistenceManager.class).ifPresent(tpm -> { 423 tpm.stopPersisting(carsTable); 424 }); 425 super.dispose(); 426 } 427 428 @Override 429 public void tableChanged(TableModelEvent e) { 430 if (Control.SHOW_PROPERTY) { 431 log.debug("Table changed"); 432 } 433 updateNumCars(); 434 } 435 436 private void updateNumCars() { 437 String count = filterCarList(InstanceManager.getDefault(CarManager.class).getList()); 438 if (showAllCars) { 439 numCars.setText(count); 440 } else { 441 String showCount = filterCarList(getSortByList()); 442 numCars.setText(showCount + "/" + count); 443 } 444 } 445 446 // only count real cars, ignore clones 447 private String filterCarList(List<Car> list) { 448 int count = 0; 449 for (Car car : list) { 450 if (!car.isClone()) { 451 count++; 452 } 453 } 454 return Integer.toString(count); 455 } 456 457 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CarsTableFrame.class); 458 459}