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.setup.Control;
019import jmri.jmrit.operations.setup.Setup;
020import jmri.jmrit.operations.trains.TrainCommon;
021import jmri.util.davidflanagan.HardcopyWriter;
022
023/**
024 * Prints engine 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 PrintEngineRosterFrame extends OperationsFrame {
034
035    boolean _isPreview;
036    EnginesTableFrame _etf;
037
038    private int numberCharPerLine = 90;
039    private int lastLength = 19;
040
041    EngineManager engineManager = InstanceManager.getDefault(EngineManager.class);
042    LocationManager locationManager = InstanceManager.getDefault(LocationManager.class);
043
044    JCheckBox printLocosWithLocation = new JCheckBox(Bundle.getMessage("PrintLocosWithLocation"));
045
046    JComboBox<String> sortByComboBox = new JComboBox<>();
047    JComboBox<String> manifestOrientationComboBox = new JComboBox<>();
048    JComboBox<Integer> fontSizeComboBox = new JComboBox<>();
049
050    JButton okayButton = new JButton(Bundle.getMessage("ButtonOK"));
051
052    public PrintEngineRosterFrame(boolean isPreview, EnginesTableFrame etf) {
053        super();
054        _isPreview = isPreview;
055        _etf = etf;
056
057        // create panel
058        JPanel pSortBy = new JPanel();
059        pSortBy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy")));
060        pSortBy.add(sortByComboBox);
061        addComboBoxAction(sortByComboBox);
062
063        JPanel pOrientation = new JPanel();
064        pOrientation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOrientation")));
065        pOrientation.add(manifestOrientationComboBox);
066
067        manifestOrientationComboBox.addItem(Setup.PORTRAIT);
068        manifestOrientationComboBox.addItem(Setup.LANDSCAPE);
069        manifestOrientationComboBox.setSelectedItem(Setup.LANDSCAPE);
070
071        JPanel pFontSize = new JPanel();
072        pFontSize.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFontSize")));
073        pFontSize.add(fontSizeComboBox);
074
075        OperationsPanel.loadFontSizeComboBox(fontSizeComboBox);
076        fontSizeComboBox.setSelectedItem(Control.reportFontSize);
077
078        JPanel pPanel = new JPanel();
079        pPanel.setLayout(new GridBagLayout());
080        JScrollPane panePanel = new JScrollPane(pPanel);
081        panePanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions")));
082        addItemLeft(pPanel, printLocosWithLocation, 0, 0);
083
084        JPanel pButtons = new JPanel();
085        pButtons.setLayout(new GridBagLayout());
086        pButtons.add(okayButton);
087        pButtons.setBorder(BorderFactory.createTitledBorder(""));
088        addButtonAction(okayButton);
089
090        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
091        getContentPane().add(pSortBy);
092        getContentPane().add(pOrientation);
093        getContentPane().add(pFontSize);
094        getContentPane().add(panePanel);
095        getContentPane().add(pButtons);
096
097        if (_isPreview) {
098            setTitle(Bundle.getMessage("MenuItemPreview"));
099        } else {
100            setTitle(Bundle.getMessage("MenuItemPrint"));
101        }
102        loadSortByComboBox(sortByComboBox);
103
104        initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight300));
105    }
106
107    @Override
108    public void initComponents() {
109        sortByComboBox.setSelectedItem(_etf.enginesModel.getSortByName());
110    }
111
112    private void loadSortByComboBox(JComboBox<String> box) {
113        box.removeAllItems();
114        for (int i =
115                _etf.enginesModel.SORTBY_NUMBER; i <= _etf.enginesModel.SORTBY_COMMENT; i++) {
116            box.addItem(_etf.enginesModel.getSortByName(i));
117        }
118        box.setSelectedItem(_etf.enginesModel.getSortByName());
119    }
120
121    @Override
122    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
123        setVisible(false);
124        printEngines();
125    }
126
127    private void printEngines() {
128        boolean landscape = false;
129        if (manifestOrientationComboBox.getSelectedItem() != null &&
130                manifestOrientationComboBox.getSelectedItem().equals(Setup.LANDSCAPE)) {
131            landscape = true;
132        }
133
134        int fontSize = (int) fontSizeComboBox.getSelectedItem();
135
136        // obtain a HardcopyWriter to do this
137        try (HardcopyWriter writer = new HardcopyWriter(new Frame(), Bundle.getMessage("TitleEngineRoster"),
138                fontSize, .5, .5, .5, .5, _isPreview, "", landscape, true, null);) {
139
140            numberCharPerLine = writer.getCharactersPerLine();
141
142            // create header
143            write(writer, createHeader());
144
145            printRoster(writer);
146
147            // and force completion of the printing
148            writer.close();
149        } catch (IOException we) {
150            log.error("Error printing ConsistRosterEntry: {}", we.getLocalizedMessage());
151        } catch (HardcopyWriter.PrintCanceledException ex) {
152            log.debug("Print cancelled");
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.enginesModel.SORTBY_TRAIN ||
169                sortByComboBox.getSelectedIndex() == _etf.enginesModel.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.enginesModel.SORTBY_OWNER) {
179            header.append(padAttribute(Bundle.getMessage("Owner"), Control.max_len_string_attibute));
180        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_MOVES) {
181            header.append(padAttribute(Bundle.getMessage("Moves"), 5));
182        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_VALUE) {
183            header.append(padAttribute(Setup.getValueLabel(), Control.max_len_string_attibute));
184        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_LAST) {
185            header.append(padAttribute(Bundle.getMessage("LastMoved"), lastLength));
186        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_RFID) {
187            header.append(padAttribute(Setup.getRfidLabel(), Control.max_len_string_attibute));
188        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_DCC_ADDRESS) {
189            header.append(padAttribute(Bundle.getMessage("DccAddress"), 5));
190        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_BUILT) {
191            header.append(padAttribute(Bundle.getMessage("Built"), Control.max_len_string_built_name));
192        } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.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.enginesModel.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.enginesModel.SORTBY_TRAIN ||
237                    sortByComboBox.getSelectedIndex() == _etf.enginesModel.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.enginesModel.SORTBY_OWNER) {
246                owner = padAttribute(engine.getOwnerName(), Control.max_len_string_attibute);
247            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_MOVES) {
248                moves = padAttribute(Integer.toString(engine.getMoves()), 5);
249            } else if (sortByComboBox
250                    .getSelectedIndex() == _etf.enginesModel.SORTBY_DCC_ADDRESS) {
251                dccAddress = padAttribute(engine.getDccAddress(), 5);
252            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_LAST) {
253                last = padAttribute(engine.getSortDate(), lastLength);
254            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_VALUE) {
255                value = padAttribute(engine.getValue(), Control.max_len_string_attibute);
256            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_RFID) {
257                rfid = padAttribute(engine.getRfid(), Control.max_len_string_attibute);
258            } else if (sortByComboBox.getSelectedIndex() == _etf.enginesModel.SORTBY_BUILT) {
259                built = padAttribute(engine.getBuilt(), Control.max_len_string_built_name);
260            } else if (sortByComboBox
261                    .getSelectedIndex() == _etf.enginesModel.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}