001package jmri.jmrit.operations.rollingstock.cars.tools; 002 003import java.awt.*; 004import java.io.IOException; 005import java.util.List; 006 007import javax.swing.*; 008 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011 012import jmri.InstanceManager; 013import jmri.jmrit.operations.OperationsFrame; 014import jmri.jmrit.operations.OperationsPanel; 015import jmri.jmrit.operations.locations.LocationManager; 016import jmri.jmrit.operations.rollingstock.cars.*; 017import jmri.jmrit.operations.setup.Control; 018import jmri.jmrit.operations.setup.Setup; 019import jmri.jmrit.operations.trains.TrainCommon; 020import jmri.util.davidflanagan.HardcopyWriter; 021 022/** 023 * Prints a summary of the car roster 024 * <p> 025 * This uses the older style printing, for compatibility with Java 1.1.8 in 026 * MacIntosh MRJ 027 * 028 * @author Bob Jacobsen Copyright (C) 2003 029 * @author Daniel Boudreau Copyright (C) 2023 030 */ 031 032public class PrintCarRosterFrame extends OperationsFrame { 033 034 boolean _isPreview; 035 CarsTableFrame _ctf; 036 037 JComboBox<String> sortByComboBox = new JComboBox<>(); 038 JComboBox<String> manifestOrientationComboBox = new JComboBox<>(); 039 JComboBox<Integer> fontSizeComboBox = new JComboBox<>(); 040 041 JCheckBox printCarsWithLocation = new JCheckBox(Bundle.getMessage("PrintCarsWithLocation")); 042 JCheckBox printCarLength = new JCheckBox(Bundle.getMessage("PrintCarLength")); 043 JCheckBox printCarWeight = new JCheckBox(Bundle.getMessage("PrintCarWeight")); 044 JCheckBox printCarColor = new JCheckBox(Bundle.getMessage("PrintCarColor")); 045 JCheckBox printCarOwner = new JCheckBox(Bundle.getMessage("PrintCarOwner")); 046 JCheckBox printCarBuilt = new JCheckBox(Bundle.getMessage("PrintCarBuilt")); 047 JCheckBox printCarLoad = new JCheckBox(Bundle.getMessage("PrintCarLoad")); 048 JCheckBox printCarKernel = new JCheckBox(Bundle.getMessage("PrintKernel")); 049 JCheckBox printCarValue = new JCheckBox( 050 Bundle.getMessage("PrintCar", Setup.getValueLabel())); 051 JCheckBox printCarRfid = new JCheckBox( 052 Bundle.getMessage("PrintCar", Setup.getRfidLabel())); 053 JCheckBox printCarLast = new JCheckBox(Bundle.getMessage("PrintCarLastMoved")); 054 JCheckBox printCarWait = new JCheckBox(Bundle.getMessage("PrintCarWait")); 055 JCheckBox printCarPickup = new JCheckBox(Bundle.getMessage("PrintCarPickup")); 056 JCheckBox printCarLocation = new JCheckBox(Bundle.getMessage("PrintCarLocation")); 057 JCheckBox printCarTrain = new JCheckBox(Bundle.getMessage("PrintCarTrain")); 058 JCheckBox printCarDestination = new JCheckBox(Bundle.getMessage("PrintCarDestination")); 059 JCheckBox printCarFinalDestination = new JCheckBox(Bundle.getMessage("PrintCarFinalDestination")); 060 JCheckBox printCarRWE = new JCheckBox(Bundle.getMessage("PrintCarReturnWhenEmpty")); 061 JCheckBox printCarRWL = new JCheckBox(Bundle.getMessage("PrintCarReturnWhenLoaded")); 062 JCheckBox printDivision = new JCheckBox(Bundle.getMessage("PrintCarDivision")); 063 JCheckBox printCarStatus = new JCheckBox(Bundle.getMessage("PrintCarStatus")); 064 JCheckBox printCarComment = new JCheckBox(Bundle.getMessage("PrintCarComment")); 065 JCheckBox printSpace = new JCheckBox(Bundle.getMessage("PrintSpace")); 066 JCheckBox printPage = new JCheckBox(Bundle.getMessage("PrintPage")); 067 068 JButton okayButton = new JButton(Bundle.getMessage("ButtonOK")); 069 070 public PrintCarRosterFrame(boolean isPreview, CarsTableFrame carsTableFrame) { 071 super(); 072 _isPreview = isPreview; 073 _ctf = carsTableFrame; 074 075 // create panel 076 JPanel pSortBy = new JPanel(); 077 pSortBy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy"))); 078 pSortBy.add(sortByComboBox); 079 addComboBoxAction(sortByComboBox); 080 081 JPanel pOrientation = new JPanel(); 082 pOrientation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOrientation"))); 083 pOrientation.add(manifestOrientationComboBox); 084 085 manifestOrientationComboBox.addItem(Setup.PORTRAIT); 086 manifestOrientationComboBox.addItem(Setup.LANDSCAPE); 087 088 JPanel pFontSize = new JPanel(); 089 pFontSize.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFontSize"))); 090 pFontSize.add(fontSizeComboBox); 091 092 OperationsPanel.loadFontSizeComboBox(fontSizeComboBox); 093 fontSizeComboBox.setSelectedItem(Control.reportFontSize); 094 095 JPanel pPanel = new JPanel(); 096 pPanel.setLayout(new GridBagLayout()); 097 JScrollPane panePanel = new JScrollPane(pPanel); 098 panePanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions"))); 099 addItemLeft(pPanel, printCarsWithLocation, 0, 0); 100 addItemLeft(pPanel, printCarLength, 0, 1); 101 addItemLeft(pPanel, printCarWeight, 0, 2); 102 addItemLeft(pPanel, printCarColor, 0, 3); 103 addItemLeft(pPanel, printCarLoad, 0, 4); 104 addItemLeft(pPanel, printCarKernel, 0, 5); 105 addItemLeft(pPanel, printCarOwner, 0, 6); 106 addItemLeft(pPanel, printCarBuilt, 0, 7); 107 addItemLeft(pPanel, printCarLast, 0, 8); 108 addItemLeft(pPanel, printCarWait, 0, 9); 109 addItemLeft(pPanel, printCarPickup, 0, 10); 110 if (Setup.isValueEnabled()) { 111 addItemLeft(pPanel, printCarValue, 0, 11); 112 } 113 if (Setup.isRfidEnabled()) { 114 addItemLeft(pPanel, printCarRfid, 0, 12); 115 } 116 addItemLeft(pPanel, printCarLocation, 0, 13); 117 addItemLeft(pPanel, printCarTrain, 0, 14); 118 addItemLeft(pPanel, printCarDestination, 0, 15); 119 addItemLeft(pPanel, printCarFinalDestination, 0, 16); 120 addItemLeft(pPanel, printCarRWE, 0, 17); 121 addItemLeft(pPanel, printCarRWL, 0, 18); 122 addItemLeft(pPanel, printDivision, 0, 19); 123 addItemLeft(pPanel, printCarStatus, 0, 20); 124 addItemLeft(pPanel, printCarComment, 0, 21); 125 addItemLeft(pPanel, printSpace, 0, 22); 126 addItemLeft(pPanel, printPage, 0, 23); 127 128 // set defaults 129 printCarsWithLocation.setSelected(false); 130 printCarLength.setSelected(true); 131 printCarWeight.setSelected(false); 132 printCarColor.setSelected(true); 133 printCarLoad.setSelected(false); 134 printCarKernel.setSelected(false); 135 printCarOwner.setSelected(false); 136 printCarBuilt.setSelected(false); 137 printCarLast.setSelected(false); 138 printCarWait.setSelected(false); 139 printCarPickup.setSelected(false); 140 printCarValue.setSelected(false); 141 printCarRfid.setSelected(false); 142 printCarLocation.setSelected(true); 143 printCarTrain.setSelected(false); 144 printCarDestination.setSelected(false); 145 printCarFinalDestination.setSelected(false); 146 printCarRWE.setSelected(false); 147 printCarRWL.setSelected(false); 148 printDivision.setSelected(false); 149 printCarStatus.setSelected(false); 150 printCarComment.setSelected(false); 151 printSpace.setSelected(false); 152 printPage.setSelected(false); 153 154 // add tool tips 155 printSpace.setToolTipText(Bundle.getMessage("TipSelectSortByLoc")); 156 printPage.setToolTipText(Bundle.getMessage("TipSelectSortByLoc")); 157 158 JPanel pButtons = new JPanel(); 159 pButtons.setLayout(new GridBagLayout()); 160 pButtons.add(okayButton); 161 pButtons.setBorder(BorderFactory.createTitledBorder("")); 162 addButtonAction(okayButton); 163 164 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 165 getContentPane().add(pSortBy); 166 getContentPane().add(pOrientation); 167 getContentPane().add(pFontSize); 168 getContentPane().add(panePanel); 169 getContentPane().add(pButtons); 170 171 initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight500)); 172 173 if (_isPreview) { 174 setTitle(Bundle.getMessage("MenuItemPreview")); 175 } else { 176 setTitle(Bundle.getMessage("MenuItemPrint")); 177 } 178 loadSortByComboBox(sortByComboBox); 179 updateLocationCheckboxes(); 180 } 181 182 private void loadSortByComboBox(JComboBox<String> box) { 183 box.removeAllItems(); 184 for (int i = _ctf.carsTableModel.SORTBY_NUMBER; i <= _ctf.carsTableModel.SORTBY_COMMENT; i++) { 185 box.addItem(_ctf.carsTableModel.getSortByName(i)); 186 } 187 box.setSelectedItem(_ctf.carsTableModel.getSortByName()); 188 } 189 190 @Override 191 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 192 setVisible(false); 193 printCars(); 194 } 195 196 @Override 197 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 198 updateLocationCheckboxes(); 199 } 200 201 private void updateLocationCheckboxes() { 202 if (sortByComboBox.getSelectedItem() != null && 203 sortByComboBox.getSelectedItem() 204 .equals(_ctf.carsTableModel.getSortByName(_ctf.carsTableModel.SORTBY_LOCATION))) { 205 printSpace.setEnabled(true); 206 printPage.setEnabled(true); 207 } else { 208 printSpace.setEnabled(false); 209 printPage.setEnabled(false); 210 printSpace.setSelected(false); 211 printPage.setSelected(false); 212 } 213 } 214 215 int numberCharPerLine; 216 217 private void printCars() { 218 boolean landscape = false; 219 if (manifestOrientationComboBox.getSelectedItem() != null && 220 manifestOrientationComboBox.getSelectedItem().equals(Setup.LANDSCAPE)) { 221 landscape = true; 222 } 223 224 int fontSize = (int) fontSizeComboBox.getSelectedItem(); 225 226 // obtain a HardcopyWriter to do this 227 try (HardcopyWriter writer = new HardcopyWriter(new Frame(), Bundle.getMessage("TitleCarRoster"), fontSize, .5, 228 .5, .5, .5, _isPreview, "", landscape, true, null)) { 229 230 numberCharPerLine = writer.getCharactersPerLine(); 231 232 printHeader(writer); 233 234 printRoster(writer); 235 236 } catch (HardcopyWriter.PrintCanceledException ex) { 237 log.debug("Print cancelled"); 238 } catch (IOException we) { 239 log.error("Error printing car roster"); 240 } 241 } 242 243 private void printHeader(HardcopyWriter writer) throws IOException { 244 String s = padAttribute(Bundle.getMessage("Number"), Control.max_len_string_print_road_number) + 245 padAttribute(Bundle.getMessage("Road"), 246 InstanceManager.getDefault(CarRoads.class).getMaxNameLength()) + 247 padAttribute(Bundle.getMessage("Type"), 248 InstanceManager.getDefault(CarTypes.class).getMaxFullNameLength()) + 249 (printCarLength.isSelected() ? Bundle.getMessage("Len") + " " : "") + 250 (printCarWeight.isSelected() ? " " : "") + 251 (printCarColor.isSelected() 252 ? padAttribute(Bundle.getMessage("Color"), 253 InstanceManager.getDefault(CarColors.class).getMaxNameLength()) 254 : "") + 255 (printCarLoad.isSelected() 256 ? padAttribute(Bundle.getMessage("Load"), 257 InstanceManager.getDefault(CarLoads.class).getMaxNameLength()) 258 : "") + 259 (printCarKernel.isSelected() ? padAttribute(("Kernel"), Control.max_len_string_attibute) : "") + 260 (printCarOwner.isSelected() 261 ? padAttribute(Bundle.getMessage("Owner"), 262 InstanceManager.getDefault(CarOwners.class).getMaxNameLength()) 263 : "") + 264 (printCarBuilt.isSelected() ? Bundle.getMessage("Built") + " " : "") + 265 (printCarLast.isSelected() ? Bundle.getMessage("LastMoved") + " " : "") + 266 (printCarWait.isSelected() ? Bundle.getMessage("Wait") + " " : "") + 267 (printCarPickup.isSelected() ? padAttribute(Bundle.getMessage("Pickup"), 10) : "") + 268 (printCarValue.isSelected() ? padAttribute(Setup.getValueLabel(), Control.max_len_string_attibute) 269 : "") + 270 (printCarRfid.isSelected() ? padAttribute(Setup.getRfidLabel(), Control.max_len_string_attibute) 271 : "") + 272 (printCarLocation.isSelected() 273 ? padAttribute(Bundle.getMessage("Location"), 274 InstanceManager.getDefault(LocationManager.class) 275 .getMaxLocationAndTrackNameLength() + 276 3) 277 : "") + 278 (printCarTrain.isSelected() 279 ? padAttribute(Bundle.getMessage("Train"), Control.max_len_string_train_name / 2) 280 : "") + 281 (printCarDestination.isSelected() 282 ? padAttribute(Bundle.getMessage("Destination"), 283 InstanceManager.getDefault(LocationManager.class) 284 .getMaxLocationAndTrackNameLength() + 285 3) 286 : "") + 287 (printCarFinalDestination.isSelected() 288 ? padAttribute(Bundle.getMessage("FinalDestination"), 289 InstanceManager.getDefault(LocationManager.class) 290 .getMaxLocationAndTrackNameLength() + 291 3) 292 : "") + 293 (printCarRWE.isSelected() 294 ? padAttribute(Bundle.getMessage("ReturnWhenEmpty"), 295 InstanceManager.getDefault(LocationManager.class) 296 .getMaxLocationAndTrackNameLength() + 297 3) 298 : "") + 299 (printCarRWL.isSelected() 300 ? padAttribute(Bundle.getMessage("ReturnWhenLoaded"), 301 InstanceManager.getDefault(LocationManager.class) 302 .getMaxLocationAndTrackNameLength() + 303 3) 304 : "") + 305 (printDivision.isSelected() ? Bundle.getMessage("HomeDivision") + " " : "") + 306 (printCarStatus.isSelected() ? Bundle.getMessage("Status") + " " : "") + 307 (printCarComment.isSelected() ? Bundle.getMessage("Comment") : ""); 308 if (s.length() > numberCharPerLine) { 309 s = s.substring(0, numberCharPerLine); 310 writer.write(Bundle.getMessage("ErrorTextPage") + NEW_LINE); 311 } 312 writer.write(s + NEW_LINE); 313 } 314 315 private void printRoster(HardcopyWriter writer) throws IOException { 316 // Loop through the Roster, printing as needed 317 String location = ""; 318 String number; 319 String road; 320 String type; 321 String length = ""; 322 String weight = ""; 323 String color = ""; 324 String owner = ""; 325 String built = ""; 326 String load = ""; 327 String kernel = ""; 328 String train = ""; 329 String destination = ""; 330 String finalDestination = ""; 331 String returnWhenEmpty = ""; 332 String returnWhenLoaded = ""; 333 String division = ""; 334 String value = ""; 335 String rfid = ""; 336 String last = ""; 337 String wait = ""; 338 String schedule = ""; 339 String status = ""; 340 String comment = ""; 341 String previousLocation = null; 342 List<Car> cars = _ctf.carsTableModel.getCarList(sortByComboBox.getSelectedIndex()); 343 for (Car car : cars) { 344 if (printCarsWithLocation.isSelected() && car.getLocation() == null) { 345 continue; // car doesn't have a location skip 346 } 347 location = ""; 348 destination = ""; 349 finalDestination = ""; 350 returnWhenEmpty = ""; 351 returnWhenLoaded = ""; 352 353 if (printCarLocation.isSelected()) { 354 if (car.getLocation() != null) { 355 location = car.getLocationName().trim() + " - " + car.getTrackName().trim(); 356 } 357 location = padAttribute(location, 358 InstanceManager.getDefault(LocationManager.class).getMaxLocationAndTrackNameLength() + 359 3); 360 } 361 // Page break between locations? 362 if (previousLocation != null && 363 !car.getLocationName().trim().equals(previousLocation) && 364 printPage.isSelected()) { 365 writer.pageBreak(); 366 printHeader(writer); 367 } // Add a line between locations? 368 else if (previousLocation != null && 369 !car.getLocationName().trim().equals(previousLocation) && 370 printSpace.isSelected()) { 371 writer.write(NEW_LINE); 372 } 373 previousLocation = car.getLocationName().trim(); 374 375 // car number 376 number = padAttribute(car.getNumber().trim(), Control.max_len_string_print_road_number); 377 // car road 378 road = padAttribute(car.getRoadName().trim(), 379 InstanceManager.getDefault(CarRoads.class).getMaxNameLength()); 380 // car type 381 type = padAttribute(car.getTypeName().trim(), 382 InstanceManager.getDefault(CarTypes.class).getMaxFullNameLength()); 383 384 if (printCarLength.isSelected()) { 385 length = padAttribute(car.getLength().trim(), Control.max_len_string_length_name); 386 } 387 if (printCarWeight.isSelected()) { 388 weight = padAttribute(car.getWeight().trim(), Control.max_len_string_weight_name); 389 } 390 if (printCarColor.isSelected()) { 391 color = padAttribute(car.getColor().trim(), 392 InstanceManager.getDefault(CarColors.class).getMaxNameLength()); 393 } 394 if (printCarLoad.isSelected()) { 395 load = padAttribute(car.getLoadName().trim(), 396 InstanceManager.getDefault(CarLoads.class).getMaxNameLength()); 397 } 398 if (printCarKernel.isSelected()) { 399 kernel = padAttribute(car.getKernelName().trim(), Control.max_len_string_attibute); 400 } 401 if (printCarOwner.isSelected()) { 402 owner = padAttribute(car.getOwnerName().trim(), 403 InstanceManager.getDefault(CarOwners.class).getMaxNameLength()); 404 } 405 if (printCarBuilt.isSelected()) { 406 built = padAttribute(car.getBuilt().trim(), Control.max_len_string_built_name); 407 } 408 if (printCarLast.isSelected()) { 409 last = padAttribute(car.getLastDate().split(" ")[0], 10); 410 } 411 if (printCarWait.isSelected()) { 412 wait = padAttribute(Integer.toString(car.getWait()), 4); 413 } 414 if (printCarPickup.isSelected()) { 415 schedule = padAttribute(car.getPickupScheduleName(), 10); 416 } 417 if (printCarValue.isSelected()) { 418 value = padAttribute(car.getValue().trim(), Control.max_len_string_attibute); 419 } 420 if (printCarRfid.isSelected()) { 421 rfid = padAttribute(car.getRfid().trim(), Control.max_len_string_attibute); 422 } 423 // pad out train to half of its maximum length 424 if (printCarTrain.isSelected()) { 425 train = padAttribute(car.getTrainName().trim(), Control.max_len_string_train_name / 2); 426 } 427 if (printCarDestination.isSelected()) { 428 if (car.getDestination() != null) { 429 destination = 430 car.getDestinationName().trim() + " - " + car.getDestinationTrackName().trim(); 431 } 432 destination = padAttribute(destination, 433 InstanceManager.getDefault(LocationManager.class).getMaxLocationAndTrackNameLength() + 434 3); 435 } 436 if (printCarFinalDestination.isSelected()) { 437 if (car.getFinalDestination() != null) { 438 finalDestination = car.getFinalDestinationName().trim(); 439 if (car.getFinalDestinationTrack() != null) { 440 finalDestination = finalDestination + 441 " - " + 442 car.getFinalDestinationTrackName().trim(); 443 } 444 } 445 finalDestination = padAttribute(finalDestination, 446 InstanceManager.getDefault(LocationManager.class).getMaxLocationAndTrackNameLength() + 447 3); 448 } 449 if (printCarRWE.isSelected()) { 450 if (car.getReturnWhenEmptyDestination() != null) { 451 returnWhenEmpty = car.getReturnWhenEmptyDestinationName().trim() + 452 " - " + 453 car.getReturnWhenEmptyDestTrackName().trim(); 454 } 455 returnWhenEmpty = padAttribute(returnWhenEmpty, 456 InstanceManager.getDefault(LocationManager.class).getMaxLocationAndTrackNameLength() + 457 3); 458 } 459 if (printCarRWL.isSelected()) { 460 if (car.getReturnWhenLoadedDestination() != null) { 461 returnWhenLoaded = car.getReturnWhenLoadedDestinationName().trim() + 462 " - " + 463 car.getReturnWhenLoadedDestTrackName().trim(); 464 } 465 returnWhenLoaded = padAttribute(returnWhenLoaded, 466 InstanceManager.getDefault(LocationManager.class).getMaxLocationAndTrackNameLength() + 467 3); 468 } 469 if (printDivision.isSelected()) { 470 division = padAttribute(car.getDivisionName(), Bundle.getMessage("HomeDivision").length()); 471 } 472 if (printCarStatus.isSelected()) { 473 status = padAttribute(car.getStatus(), Bundle.getMessage("Status").length()); 474 } 475 // comment gets trimmed by line length 476 if (printCarComment.isSelected()) { 477 comment = car.getComment().trim(); 478 } 479 480 String s = number + 481 road + 482 type + 483 length + 484 weight + 485 color + 486 load + 487 kernel + 488 owner + 489 built + 490 last + 491 wait + 492 schedule + 493 value + 494 rfid + 495 location + 496 train + 497 destination + 498 finalDestination + 499 returnWhenEmpty + 500 returnWhenLoaded + 501 division + 502 status + 503 comment; 504 505 if (s.length() > numberCharPerLine) { 506 s = s.substring(0, numberCharPerLine); 507 } 508 writer.write(s + NEW_LINE); 509 } 510 } 511 512 private String padAttribute(String attribute, int length) { 513 return TrainCommon.padAndTruncate(attribute, length) + TrainCommon.SPACE; 514 } 515 516 private final static Logger log = LoggerFactory.getLogger(PrintCarRosterFrame.class); 517}