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