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