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