001package jmri.jmrit.operations.trains.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.routes.Route; 017import jmri.jmrit.operations.routes.RouteLocation; 018import jmri.jmrit.operations.setup.Control; 019import jmri.jmrit.operations.setup.Setup; 020import jmri.jmrit.operations.trains.*; 021import jmri.jmrit.operations.trains.gui.TrainsTableFrame; 022import jmri.jmrit.operations.trains.gui.TrainsTableModel; 023import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 024import jmri.util.davidflanagan.HardcopyWriter; 025 026/** 027 * Prints a summary of a train or trains. The trains list is controlled by the 028 * "Show All" checkbox and the "Build" checkboxes in the TrainsTableFrame. 029 * <p> 030 * This uses the older style printing, for compatibility with Java 1.1.8 in 031 * Macintosh MRJ 032 * 033 * @author Bob Jacobsen Copyright (C) 2003 034 * @author Dennis Miller Copyright (C) 2005 035 * @author Daniel Boudreau Copyright (C) 2009, 2023 036 */ 037public class PrintTrainsFrame extends OperationsFrame { 038 039 static final String TAB = "\t"; // NOI18N 040 static final char FORM_FEED = '\f'; // NOI18N 041 042 public static final int MAX_NAME_LENGTH = Control.max_len_string_train_name - 10; 043 044 boolean _isPreview; 045 Train _train; 046 TrainsTableFrame _trainsTableFrame; 047 048 JComboBox<String> sortByComboBox = new JComboBox<>(); 049 JComboBox<String> manifestOrientationComboBox = new JComboBox<>(); 050 JComboBox<Integer> fontSizeComboBox = new JComboBox<>(); 051 052 JCheckBox printSummary = new JCheckBox(Bundle.getMessage("PrintSummary")); 053 JCheckBox printDetails = new JCheckBox(Bundle.getMessage("PrintDetails")); 054 JButton okayButton = new JButton(Bundle.getMessage("ButtonOK")); 055 056 public PrintTrainsFrame(boolean isPreview, Train train) { 057 _isPreview = isPreview; 058 _train = train; 059 printTrain(); 060 } 061 062 public PrintTrainsFrame(boolean isPreview, TrainsTableFrame trainsTableFrame) { 063 _isPreview = isPreview; 064 _trainsTableFrame = trainsTableFrame; 065 066 // create panel 067 JPanel pSortBy = new JPanel(); 068 pSortBy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SortBy"))); 069 pSortBy.add(sortByComboBox); 070 071 loadSortByComboBox(sortByComboBox); 072 addComboBoxAction(sortByComboBox); 073 074 JPanel pOrientation = new JPanel(); 075 pOrientation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOrientation"))); 076 pOrientation.add(manifestOrientationComboBox); 077 078 manifestOrientationComboBox.addItem(Setup.PORTRAIT); 079 manifestOrientationComboBox.addItem(Setup.LANDSCAPE); 080 // manifestOrientationComboBox.setSelectedItem(Setup.LANDSCAPE); 081 082 JPanel pFontSize = new JPanel(); 083 pFontSize.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFontSize"))); 084 pFontSize.add(fontSizeComboBox); 085 086 OperationsPanel.loadFontSizeComboBox(fontSizeComboBox); 087 fontSizeComboBox.setSelectedItem(Control.reportFontSize); 088 089 // create panel 090 JPanel pPanel = new JPanel(); 091 pPanel.setLayout(new GridBagLayout()); 092 pPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions"))); 093 addItemLeft(pPanel, printSummary, 0, 0); 094 addItemLeft(pPanel, printDetails, 0, 1); 095 096 printSummary.setSelected(true); 097 printDetails.setSelected(true); 098 099 // add tool tips 100 JPanel pButtons = new JPanel(); 101 pButtons.setLayout(new GridBagLayout()); 102 pButtons.add(okayButton); 103 addButtonAction(okayButton); 104 105 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 106 getContentPane().add(pSortBy); 107 getContentPane().add(pOrientation); 108 getContentPane().add(pFontSize); 109 getContentPane().add(pPanel); 110 getContentPane().add(pButtons); 111 setPreferredSize(null); 112 if (_isPreview) { 113 setTitle(Bundle.getMessage("MenuItemPreview")); 114 } else { 115 setTitle(Bundle.getMessage("MenuItemPrint")); 116 } 117 initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight250)); 118 } 119 120 @Override 121 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 122 setVisible(false); 123 printTrains(); 124 } 125 126 private void printTrains() { 127 if (!printSummary.isSelected() && !printDetails.isSelected()) { 128 return; 129 } 130 131 // obtain a HardcopyWriter to do this 132 boolean isLandscape = false; 133 if (manifestOrientationComboBox.getSelectedItem() != null && 134 manifestOrientationComboBox.getSelectedItem().equals(Setup.LANDSCAPE)) { 135 isLandscape = true; 136 } 137 138 int fontSize = (int) fontSizeComboBox.getSelectedItem(); 139 try (HardcopyWriter writer = new HardcopyWriter(new Frame(), Bundle.getMessage("TitleTrainsTable"), 140 fontSize, .5, .5, .5, .5, _isPreview, "", isLandscape, true, null, null);) { 141 142 List<Train> trains = _trainsTableFrame.getSortByList((String) sortByComboBox.getSelectedItem()); 143 144 if (printSummary.isSelected()) { 145 printSummaryTrains(writer, trains, _trainsTableFrame); 146 if (printDetails.isSelected()) { 147 writer.write(FORM_FEED); // new page 148 } 149 } 150 151 if (printDetails.isSelected()) { 152 // now do the details for each train 153 for (Train train : trains) { 154 if ((train.isBuildEnabled() || _trainsTableFrame.showAllBox.isSelected()) && 155 train.getRoute() != null) { 156 List<RouteLocation> route = train.getRoute().getLocationsBySequenceList(); 157 // determine if another detailed summary can fit on the same page 158 if (writer.getLinesPerPage() - writer.getCurrentLineNumber() < route.size() + 159 getNumberOfLines(writer, Bundle.getMessage("Comment") + ": " + train.getComment()) + 160 NUMBER_OF_HEADER_LINES) { 161 writer.write(FORM_FEED); 162 } else if (writer.getCurrentLineNumber() > 0) { 163 writer.write(NEW_LINE); 164 } 165 printTrain(writer, train); 166 } 167 } 168 } 169 } catch (HardcopyWriter.PrintCanceledException ex) { 170 log.debug("Print cancelled"); 171 } catch (IOException e1) { 172 log.error("Exception in print train details: {}", e1.getLocalizedMessage()); 173 } 174 } 175 176 private void printSummaryTrains(HardcopyWriter writer, List<Train> trains, TrainsTableFrame trainsTableFrame) 177 throws IOException { 178 int maxLineLength = writer.getCharactersPerLine() - 1; 179 int maxTrainNameLength = InstanceManager.getDefault(TrainManager.class).getMaxTrainNameLength(); 180 int maxLocationNameLength = InstanceManager.getDefault(LocationManager.class).getMaxLocationNameLength(); 181 String s = Bundle.getMessage("Time") + 182 " " + 183 truncate(Bundle.getMessage("Name"), maxTrainNameLength) + 184 truncate(Bundle.getMessage("Description")) + 185 truncate(Bundle.getMessage("Route")) + 186 truncate(Bundle.getMessage("Departs"), maxLocationNameLength) + 187 truncate(Bundle.getMessage("Terminates"), maxLocationNameLength); 188 writer.write(truncate(s, maxLineLength) + NEW_LINE); 189 for (Train train : trains) { 190 if (train.isBuildEnabled() || trainsTableFrame.showAllBox.isSelected()) { 191 String name = truncate(train.getName(), maxTrainNameLength); 192 String desc = truncate(train.getDescription()); 193 String route = truncate(train.getTrainRouteName()); 194 String departs = truncate(train.getTrainDepartsName(), maxLocationNameLength); 195 String terminates = truncate(train.getTrainTerminatesName(), maxLocationNameLength); 196 197 s = train.getDepartureTime() + 198 " " + 199 name + 200 desc + 201 route + 202 departs + 203 terminates; 204 writer.write(truncate(s, maxLineLength) + NEW_LINE); 205 } 206 } 207 } 208 209 private String truncate(String string) { 210 return truncate(string, MAX_NAME_LENGTH); 211 } 212 213 private String truncate(String string, int length) { 214 return TrainCommon.padAndTruncate(string, length) + TrainCommon.SPACE; 215 } 216 217 private void printTrain() { 218 if (_train == null) { 219 return; 220 } 221 // obtain a HardcopyWriter to do this 222 try (HardcopyWriter writer = new HardcopyWriter(new Frame(), Bundle.getMessage("TitleTrain", _train.getName()), 223 Control.reportFontSize, .5, .5, .5, .5, _isPreview)) { 224 225 printTrain(writer, _train); 226 } catch (HardcopyWriter.PrintCanceledException ex) { 227 log.debug("Print cancelled"); 228 } catch (IOException ex) { 229 log.error("Exception in print train: {}", ex.getLocalizedMessage()); 230 } 231 } 232 233 // 7 lines of header plus NEW_LINE at start 234 private static final int NUMBER_OF_HEADER_LINES = 8; 235 236 private void printTrain(HardcopyWriter writer, Train train) throws IOException { 237 String s = Bundle.getMessage("Name") + ": " + train.getName() + NEW_LINE; 238 writer.write(s); 239 s = Bundle.getMessage("Description") + ": " + train.getDescription() + NEW_LINE; 240 writer.write(s); 241 s = Bundle.getMessage("Departs") + ": " + train.getTrainDepartsName() + NEW_LINE; 242 writer.write(s); 243 s = Bundle.getMessage("DepartTime") + ": " + train.getDepartureTime() + NEW_LINE; 244 writer.write(s); 245 s = Bundle.getMessage("Terminates") + ": " + train.getTrainTerminatesName() + NEW_LINE; 246 writer.write(s); 247 248 writer.write(NEW_LINE); 249 250 s = Bundle.getMessage("Route") + ": " + train.getTrainRouteName() + NEW_LINE; 251 writer.write(s); 252 Route route = train.getRoute(); 253 if (route != null) { 254 for (RouteLocation rl : route.getLocationsBySequenceList()) { 255 s = TAB + rl.getName() + NEW_LINE; 256 writer.write(s); 257 } 258 } 259 if (!train.getComment().equals(Train.NONE)) { 260 s = Bundle.getMessage("Comment") + ": " + train.getComment() + NEW_LINE; 261 writer.write(s); 262 } 263 } 264 265 private void loadSortByComboBox(JComboBox<String> box) { 266 box.addItem(TrainsTableModel.IDCOLUMNNAME); 267 box.addItem(TrainsTableModel.TIMECOLUMNNAME); 268 box.addItem(TrainsTableModel.NAMECOLUMNNAME); 269 box.addItem(TrainsTableModel.DESCRIPTIONCOLUMNNAME); 270 box.addItem(TrainsTableModel.ROUTECOLUMNNAME); 271 box.addItem(TrainsTableModel.DEPARTSCOLUMNNAME); 272 box.addItem(TrainsTableModel.TERMINATESCOLUMNNAME); 273 box.addItem(TrainsTableModel.STATUSCOLUMNNAME); 274 275 box.setSelectedItem(_trainsTableFrame.getSortBy()); 276 } 277 278 private int getNumberOfLines(HardcopyWriter writer, String string) { 279 String[] lines = string.split(NEW_LINE); 280 int count = lines.length; 281 // any long lines that exceed the page width? 282 for (String line : lines) { 283 int add = line.length() / writer.getCharactersPerLine(); 284 count = count + add; 285 } 286 return count; 287 } 288 289 private final static Logger log = LoggerFactory.getLogger(PrintTrainsFrame.class); 290}