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