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