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