001package jmri.jmrit.operations.rollingstock.engines.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.CarRoads;
017import jmri.jmrit.operations.rollingstock.engines.*;
018import jmri.jmrit.operations.rollingstock.engines.gui.EnginesTableFrame;
019import jmri.jmrit.operations.setup.Control;
020import jmri.jmrit.operations.setup.Setup;
021import jmri.jmrit.operations.trains.trainbuilder.TrainCommon;
022import jmri.util.davidflanagan.HardcopyWriter;
023
024/**
025 * Prints engine roster.
026 * <p>
027 * This uses the older style printing, for compatibility with Java 1.1.8 in
028 * Macintosh MRJ
029 *
030 * @author Bob Jacobsen Copyright (C) 2003
031 * @author Daniel Boudreau Copyright (C) 2023
032 */
033
034public class PrintEngineRosterFrame extends OperationsFrame {
035
036    boolean _isPreview;
037    EnginesTableFrame _etf;
038
039    private int numberCharPerLine = 90;
040    private int lastLength = 19;
041
042    EngineManager engineManager = InstanceManager.getDefault(EngineManager.class);
043    LocationManager locationManager = InstanceManager.getDefault(LocationManager.class);
044
045    JCheckBox printLocosWithLocation = new JCheckBox(Bundle.getMessage("PrintLocosWithLocation"));
046
047    JComboBox<String> sortByComboBox = new JComboBox<>();
048    JComboBox<String> manifestOrientationComboBox = new JComboBox<>();
049    JComboBox<Integer> fontSizeComboBox = new JComboBox<>();
050
051    JButton okayButton = new JButton(Bundle.getMessage("ButtonOK"));
052
053    public PrintEngineRosterFrame(boolean isPreview, EnginesTableFrame etf) {
054        super();
055        _isPreview = isPreview;
056        _etf = etf;
057
058        // create panel
059        JPanel pSortBy = new JPanel();
060        pSortBy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy")));
061        pSortBy.add(sortByComboBox);
062        addComboBoxAction(sortByComboBox);
063
064        JPanel pOrientation = new JPanel();
065        pOrientation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOrientation")));
066        pOrientation.add(manifestOrientationComboBox);
067
068        manifestOrientationComboBox.addItem(Setup.PORTRAIT);
069        manifestOrientationComboBox.addItem(Setup.LANDSCAPE);
070        manifestOrientationComboBox.setSelectedItem(Setup.LANDSCAPE);
071
072        JPanel pFontSize = new JPanel();
073        pFontSize.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFontSize")));
074        pFontSize.add(fontSizeComboBox);
075
076        OperationsPanel.loadFontSizeComboBox(fontSizeComboBox);
077        fontSizeComboBox.setSelectedItem(Control.reportFontSize);
078
079        JPanel pPanel = new JPanel();
080        pPanel.setLayout(new GridBagLayout());
081        JScrollPane panePanel = new JScrollPane(pPanel);
082        panePanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions")));
083        addItemLeft(pPanel, printLocosWithLocation, 0, 0);
084
085        JPanel pButtons = new JPanel();
086        pButtons.setLayout(new GridBagLayout());
087        pButtons.add(okayButton);
088        pButtons.setBorder(BorderFactory.createTitledBorder(""));
089        addButtonAction(okayButton);
090
091        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
092        getContentPane().add(pSortBy);
093        getContentPane().add(pOrientation);
094        getContentPane().add(pFontSize);
095        getContentPane().add(panePanel);
096        getContentPane().add(pButtons);
097
098        if (_isPreview) {
099            setTitle(Bundle.getMessage("MenuItemPreview"));
100        } else {
101            setTitle(Bundle.getMessage("MenuItemPrint"));
102        }
103        loadSortByComboBox(sortByComboBox);
104
105        initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight300));
106    }
107
108    @Override
109    public void initComponents() {
110        sortByComboBox.setSelectedItem(_etf.enginesTableModel.getSortByName());
111    }
112
113    private void loadSortByComboBox(JComboBox<String> box) {
114        box.removeAllItems();
115        for (int i =
116                _etf.enginesTableModel.SORTBY_NUMBER; i <= _etf.enginesTableModel.SORTBY_COMMENT; i++) {
117            box.addItem(_etf.enginesTableModel.getSortByName(i));
118        }
119        box.setSelectedItem(_etf.enginesTableModel.getSortByName());
120    }
121
122    @Override
123    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
124        setVisible(false);
125        printEngines();
126    }
127
128    private void printEngines() {
129        boolean isLandscape = false;
130        if (manifestOrientationComboBox.getSelectedItem() != null &&
131                manifestOrientationComboBox.getSelectedItem().equals(Setup.LANDSCAPE)) {
132            isLandscape = true;
133        }
134
135        int fontSize = (int) fontSizeComboBox.getSelectedItem();
136
137        // obtain a HardcopyWriter to do this
138        try (HardcopyWriter writer = new HardcopyWriter(new Frame(), Bundle.getMessage("TitleEngineRoster"),
139                null, null, fontSize, .5 * 72, .5 * 72, .5 * 72, .5 * 72, _isPreview, "", isLandscape, true, null,
140                null)) {
141
142            numberCharPerLine = writer.getCharactersPerLine();
143
144            // create header
145            write(writer, createHeader());
146
147            printRoster(writer);
148
149        } catch (IOException we) {
150            log.error("Error printing ConsistRosterEntry: {}", we.getLocalizedMessage());
151        } catch (HardcopyWriter.PrintCanceledException ex) {
152            log.debug("Print canceled");
153        }
154    }
155
156    private String createHeader() {
157        StringBuffer header = new StringBuffer();
158
159        header.append(padAttribute(Bundle.getMessage("Number"), Control.max_len_string_print_road_number) +
160                padAttribute(Bundle.getMessage("Road"),
161                        InstanceManager.getDefault(CarRoads.class).getMaxNameLength()) +
162                padAttribute(Bundle.getMessage("Model"),
163                        InstanceManager.getDefault(EngineModels.class).getMaxNameLength()) +
164                padAttribute(Bundle.getMessage("Type"),
165                        InstanceManager.getDefault(EngineTypes.class).getMaxNameLength()) +
166                padAttribute(Bundle.getMessage("Len"), Control.max_len_string_length_name));
167
168        if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_TRAIN ||
169                sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_DESTINATION) {
170            header.append(padAttribute(Bundle.getMessage("Train"), Control.max_len_string_train_name / 2));
171        } else {
172            header.append(padAttribute(Bundle.getMessage("Consist"),
173                    InstanceManager.getDefault(ConsistManager.class).getMaxNameLength()));
174        }
175        header.append(padAttribute(Bundle.getMessage("Location"),
176                locationManager.getMaxLocationAndTrackNameLength() + 3));
177        // one of eight user selections
178        if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_OWNER) {
179            header.append(padAttribute(Bundle.getMessage("Owner"), Control.max_len_string_attibute));
180        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_MOVES) {
181            header.append(padAttribute(Bundle.getMessage("Moves"), 5));
182        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_VALUE) {
183            header.append(padAttribute(Setup.getValueLabel(), Control.max_len_string_attibute));
184        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_LAST) {
185            header.append(padAttribute(Bundle.getMessage("LastMoved"), lastLength));
186        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_RFID) {
187            header.append(padAttribute(Setup.getRfidLabel(), Control.max_len_string_attibute));
188        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_DCC_ADDRESS) {
189            header.append(padAttribute(Bundle.getMessage("DccAddress"), 5));
190        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_BUILT) {
191            header.append(padAttribute(Bundle.getMessage("Built"), Control.max_len_string_built_name));
192        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_DESTINATION) {
193            header.append(Bundle.getMessage("Destination"));
194        } else {
195            header.append(padAttribute(Bundle.getMessage("Comment"), engineManager.getMaxCommentLength()));
196        }
197        return header.toString() + NEW_LINE;
198    }
199
200    private void printRoster(HardcopyWriter writer) throws IOException {
201        // Loop through the Roster, printing as needed
202        String number;
203        String road;
204        String model;
205        String type;
206        String length;
207        String train = "";
208        String consist = "";
209        String location = "";
210        String moves = "";
211        String owner = "";
212        String built = "";
213        String dccAddress = "";
214        String value = "";
215        String rfid = "";
216        String last = "";
217        String comment = "";
218
219        List<Engine> engines = _etf.enginesTableModel.getEngineList(sortByComboBox.getSelectedIndex());
220        for (Engine engine : engines) {
221            if (printLocosWithLocation.isSelected() && engine.getLocation() == null) {
222                continue;
223            }
224            String destination = "";
225            // engine number, road, model, type, and length are always printed
226            number = padAttribute(engine.getNumber(), Control.max_len_string_print_road_number);
227            road = padAttribute(engine.getRoadName(),
228                    InstanceManager.getDefault(CarRoads.class).getMaxNameLength());
229            model = padAttribute(engine.getModel(),
230                    InstanceManager.getDefault(EngineModels.class).getMaxNameLength());
231            type = padAttribute(engine.getTypeName(),
232                    InstanceManager.getDefault(EngineTypes.class).getMaxNameLength());
233            length = padAttribute(engine.getLength(), Control.max_len_string_length_name);
234
235            // show train or consist name
236            if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_TRAIN ||
237                    sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_DESTINATION) {
238                train = padAttribute(engine.getTrainName().trim(), Control.max_len_string_train_name / 2);
239            } else {
240                consist = padAttribute(engine.getConsistName(),
241                        InstanceManager.getDefault(ConsistManager.class).getMaxNameLength());
242            }
243
244            // show one of 8 options, comment is default
245            if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_OWNER) {
246                owner = padAttribute(engine.getOwnerName(), Control.max_len_string_attibute);
247            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_MOVES) {
248                moves = padAttribute(Integer.toString(engine.getMoves()), 5);
249            } else if (sortByComboBox
250                    .getSelectedIndex() == _etf.enginesTableModel.SORTBY_DCC_ADDRESS) {
251                dccAddress = padAttribute(engine.getDccAddress(), 5);
252            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_LAST) {
253                last = padAttribute(engine.getSortDate(), lastLength);
254            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_VALUE) {
255                value = padAttribute(engine.getValue(), Control.max_len_string_attibute);
256            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_RFID) {
257                rfid = padAttribute(engine.getRfid(), Control.max_len_string_attibute);
258            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesTableModel.SORTBY_BUILT) {
259                built = padAttribute(engine.getBuilt(), Control.max_len_string_built_name);
260            } else if (sortByComboBox
261                    .getSelectedIndex() == _etf.enginesTableModel.SORTBY_DESTINATION) {
262                if (engine.getDestination() != null) {
263                    destination = padAttribute(
264                            engine.getDestinationName() + " - " + engine.getDestinationTrackName(),
265                            locationManager.getMaxLocationAndTrackNameLength() +
266                                    3);
267                }
268            } else {
269                comment = padAttribute(engine.getComment(), engineManager.getMaxCommentLength());
270            }
271
272            if (!engine.getLocationName().equals(Engine.NONE)) {
273                location = padAttribute(engine.getLocationName() + " - " + engine.getTrackName(),
274                        locationManager.getMaxLocationAndTrackNameLength() + 3);
275            } else {
276                location = padAttribute("",
277                        locationManager.getMaxLocationAndTrackNameLength() + 3);
278            }
279
280            String s = number +
281                    road +
282                    model +
283                    type +
284                    length +
285                    consist +
286                    train +
287                    location +
288                    moves +
289                    owner +
290                    value +
291                    rfid +
292                    dccAddress +
293                    built +
294                    last +
295                    comment +
296                    destination;
297            write(writer, s);
298        }
299    }
300
301    private void write(HardcopyWriter writer, String s) throws IOException {
302        if (s.length() > numberCharPerLine) {
303            s = s.substring(0, numberCharPerLine);
304        }
305        writer.write(s + NEW_LINE);
306    }
307
308    private String padAttribute(String attribute, int length) {
309        return TrainCommon.padAndTruncate(attribute, length) + TrainCommon.SPACE;
310    }
311
312    private final static Logger log = LoggerFactory.getLogger(PrintEngineRosterFrame.class);
313}