001package jmri.jmrit.operations.setup.gui;
002
003import java.awt.*;
004import java.awt.event.ActionEvent;
005import java.awt.event.ActionListener;
006import java.io.File;
007import java.util.ArrayList;
008import java.util.Arrays;
009import java.util.List;
010
011import javax.print.attribute.standard.Sides;
012import javax.swing.*;
013
014import jmri.InstanceManager;
015import jmri.jmrit.operations.OperationsPanel;
016import jmri.jmrit.operations.setup.*;
017import jmri.jmrit.operations.trains.TrainManager;
018import jmri.jmrit.operations.trains.trainbuilder.TrainCommon;
019import jmri.util.FileUtil;
020import jmri.util.swing.FontComboUtil;
021import jmri.util.swing.JmriJOptionPane;
022
023/**
024 * Frame for user edit of manifest and switch list print options
025 *
026 * @author Dan Boudreau Copyright (C) 2008, 2010, 2011, 2012, 2013, 2025, 2026
027 */
028public class PrintOptionPanel extends OperationsPreferencesPanel implements java.beans.PropertyChangeListener {
029
030    private String ADD = "+";
031    private String DELETE = "-";
032
033    // labels
034    JLabel logoURL = new JLabel("");
035
036    // major buttons
037    JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
038    JButton addLogoButton = new JButton(Bundle.getMessage("AddLogo"));
039    JButton removeLogoButton = new JButton(Bundle.getMessage("RemoveLogo"));
040
041    JButton addEngPickupComboboxButton = new JButton(ADD);
042    JButton deleteEngPickupComboboxButton = new JButton(DELETE);
043    JButton addEngDropComboboxButton = new JButton(ADD);
044    JButton deleteEngDropComboboxButton = new JButton(DELETE);
045    JButton addCarPickupComboboxButton = new JButton(ADD);
046    JButton deleteCarPickupComboboxButton = new JButton(DELETE);
047    JButton addCarDropComboboxButton = new JButton(ADD);
048    JButton deleteCarDropComboboxButton = new JButton(DELETE);
049    JButton addLocalComboboxButton = new JButton(ADD);
050    JButton deleteLocalComboboxButton = new JButton(DELETE);
051    JButton addSwitchListPickupComboboxButton = new JButton(ADD);
052    JButton deleteSwitchListPickupComboboxButton = new JButton(DELETE);
053    JButton addSwitchListDropComboboxButton = new JButton(ADD);
054    JButton deleteSwitchListDropComboboxButton = new JButton(DELETE);
055    JButton addSwitchListLocalComboboxButton = new JButton(ADD);
056    JButton deleteSwitchListLocalComboboxButton = new JButton(DELETE);
057    JButton addMiaComboboxButton = new JButton(ADD);
058    JButton deleteMiaComboboxButton = new JButton(DELETE);
059
060    // check boxes
061    JCheckBox tabFormatCheckBox = new JCheckBox(Bundle.getMessage("TabFormat"));
062    JCheckBox formatSwitchListCheckBox = new JCheckBox(Bundle.getMessage("SameAsManifest"));
063    JCheckBox editManifestCheckBox = new JCheckBox(Bundle.getMessage("UseTextEditor"));
064    JCheckBox printLocCommentsCheckBox = new JCheckBox(Bundle.getMessage("PrintLocationComments"));
065    JCheckBox printRouteCommentsCheckBox = new JCheckBox(Bundle.getMessage("PrintRouteComments"));
066    JCheckBox printLoadsEmptiesCheckBox = new JCheckBox(Bundle.getMessage("PrintLoadsEmpties"));
067    JCheckBox printCabooseLoadCheckBox = new JCheckBox(Bundle.getMessage("PrintCabooseLoad"));
068    JCheckBox printPassengerLoadCheckBox = new JCheckBox(Bundle.getMessage("PrintPassengerLoad"));
069    JCheckBox printTrainScheduleNameCheckBox = new JCheckBox(Bundle.getMessage("PrintTrainScheduleName"));
070    JCheckBox use12hrFormatCheckBox = new JCheckBox(Bundle.getMessage("12hrFormat"));
071    JCheckBox printValidCheckBox = new JCheckBox(Bundle.getMessage("PrintValid"));
072    JCheckBox sortByTrackCheckBox = new JCheckBox(Bundle.getMessage("SortByTrack"));
073    JCheckBox noPageBreaksCheckBox = new JCheckBox(Bundle.getMessage("NoPageBreaks"));
074    JCheckBox printHeadersCheckBox = new JCheckBox(Bundle.getMessage("PrintHeaders"));
075    JCheckBox printPageHeaderCheckBox = new JCheckBox(Bundle.getMessage("PrintPageHeader"));
076    JCheckBox truncateCheckBox = new JCheckBox(Bundle.getMessage("Truncate"));
077    JCheckBox manifestDepartureTimeCheckBox = new JCheckBox(Bundle.getMessage("DepartureTime"));
078    JCheckBox switchListDepartureTimeCheckBox = new JCheckBox(Bundle.getMessage("DepartureTime"));
079    JCheckBox trackSummaryCheckBox = new JCheckBox(Bundle.getMessage("TrackSummary"));
080    JCheckBox routeLocationCheckBox = new JCheckBox(Bundle.getMessage("RouteLocation"));
081    JCheckBox groupCarMovesCheckBox = new JCheckBox(Bundle.getMessage("GroupCarMoves"));
082    JCheckBox printLocoLastCheckBox = new JCheckBox(Bundle.getMessage("PrintLocoLast"));
083    JCheckBox boldCheckBox = new JCheckBox();
084
085    // text field
086    JTextField pickupEngPrefix = new JTextField(10);
087    JTextField dropEngPrefix = new JTextField(10);
088    JTextField pickupCarPrefix = new JTextField(10);
089    JTextField dropCarPrefix = new JTextField(10);
090    JTextField localPrefix = new JTextField(10);
091    JTextField switchListPickupCarPrefix = new JTextField(10);
092    JTextField switchListDropCarPrefix = new JTextField(10);
093    JTextField switchListLocalPrefix = new JTextField(10);
094    JTextField hazardousTextField = new JTextField(20);
095
096    // text area
097    JTextArea miaCommentTextArea = new JTextArea(4, 90);
098
099    JScrollPane commentScroller = new JScrollPane(miaCommentTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
100            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
101
102    // combo boxes
103    JComboBox<String> fontComboBox = new JComboBox<>();
104    JComboBox<String> manifestFormatComboBox = Setup.getManifestFormatComboBox();
105    JComboBox<String> manifestOrientationComboBox = Setup.getOrientationComboBox();
106    JComboBox<Integer> fontSizeComboBox = new JComboBox<>();
107    JComboBox<String> switchListOrientationComboBox = Setup.getOrientationComboBox();
108    JComboBox<Sides> printDuplexComboBox = new JComboBox<>();
109    JColorChooser pickupEngineColorChooser = new JColorChooser();
110    JColorChooser dropEngineColorChooser = new JColorChooser();
111    JColorChooser pickupColorChooser = new JColorChooser();
112    JColorChooser dropColorChooser = new JColorChooser();
113    JColorChooser localColorChooser = new JColorChooser();
114    JColorChooser missingCarColorChooser = new JColorChooser();
115
116    // message formats
117    List<JComboBox<String>> enginePickupMessageList = new ArrayList<>();
118    List<JComboBox<String>> engineDropMessageList = new ArrayList<>();
119    List<JComboBox<String>> carPickupMessageList = new ArrayList<>();
120    List<JComboBox<String>> carDropMessageList = new ArrayList<>();
121    List<JComboBox<String>> localMessageList = new ArrayList<>();
122    List<JComboBox<String>> switchListCarPickupMessageList = new ArrayList<>();
123    List<JComboBox<String>> switchListCarDropMessageList = new ArrayList<>();
124    List<JComboBox<String>> switchListLocalMessageList = new ArrayList<>();
125    List<JComboBox<String>> miaMessageList = new ArrayList<>();
126
127    // manifest panels
128    JPanel pManifest = new JPanel();
129    JPanel pEngPickup = new JPanel();
130    JPanel pEngDrop = new JPanel();
131    JPanel pPickup = new JPanel();
132    JPanel pDrop = new JPanel();
133    JPanel pLocal = new JPanel();
134
135    // switch list panels
136    JPanel pSwitchListOrientation = new JPanel();
137    JPanel pSwPickup = new JPanel();
138    JPanel pSwDrop = new JPanel();
139    JPanel pSwLocal = new JPanel();
140    
141    JPanel pMia = new JPanel();
142
143    public PrintOptionPanel() {
144
145        // tool tips
146        saveButton.setToolTipText(Bundle.getMessage("SaveToolTip"));
147        addLogoButton.setToolTipText(Bundle.getMessage("AddLogoToolTip"));
148        removeLogoButton.setToolTipText(Bundle.getMessage("RemoveLogoToolTip"));
149        tabFormatCheckBox.setToolTipText(Bundle.getMessage("TabComment"));
150        printLocCommentsCheckBox.setToolTipText(Bundle.getMessage("AddLocationComments"));
151        printRouteCommentsCheckBox.setToolTipText(Bundle.getMessage("AddRouteComments"));
152        printLoadsEmptiesCheckBox.setToolTipText(Bundle.getMessage("LoadsEmptiesComment"));
153        printCabooseLoadCheckBox.setToolTipText(Bundle.getMessage("CabooseLoadTip"));
154        printPassengerLoadCheckBox.setToolTipText(Bundle.getMessage("PassengerLoadTip"));
155        printTrainScheduleNameCheckBox.setToolTipText(Bundle.getMessage("ShowTrainScheduleTip"));
156        use12hrFormatCheckBox.setToolTipText(Bundle.getMessage("Use12hrFormatTip"));
157        printValidCheckBox.setToolTipText(Bundle.getMessage("PrintValidTip"));
158        sortByTrackCheckBox.setToolTipText(Bundle.getMessage("SortByTrackTip"));
159        noPageBreaksCheckBox.setToolTipText(Bundle.getMessage("NoPageBreaksTip"));
160        printHeadersCheckBox.setToolTipText(Bundle.getMessage("PrintHeadersTip"));
161        printPageHeaderCheckBox.setToolTipText(Bundle.getMessage("PrintPageHeaderTip"));
162        truncateCheckBox.setToolTipText(Bundle.getMessage("TruncateTip"));
163        manifestDepartureTimeCheckBox.setToolTipText(Bundle.getMessage("DepartureTimeTip"));
164        switchListDepartureTimeCheckBox.setToolTipText(Bundle.getMessage("SwitchListDepartureTimeTip"));
165        routeLocationCheckBox.setToolTipText(Bundle.getMessage("RouteLocationTip"));
166        editManifestCheckBox.setToolTipText(Bundle.getMessage("UseTextEditorTip"));
167        trackSummaryCheckBox.setToolTipText(Bundle.getMessage("TrackSummaryTip"));
168        groupCarMovesCheckBox.setToolTipText(Bundle.getMessage("GroupCarsTip"));
169        printLocoLastCheckBox.setToolTipText(Bundle.getMessage("LocoLastTip"));
170
171        addEngPickupComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
172        deleteEngPickupComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
173        addEngDropComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
174        deleteEngDropComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
175
176        addCarPickupComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
177        deleteCarPickupComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
178        addCarDropComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
179        deleteCarDropComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
180        addLocalComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
181        deleteLocalComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
182
183        addSwitchListPickupComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
184        deleteSwitchListPickupComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
185        addSwitchListDropComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
186        deleteSwitchListDropComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
187        addSwitchListLocalComboboxButton.setToolTipText(Bundle.getMessage("AddMessageComboboxTip"));
188        deleteSwitchListLocalComboboxButton.setToolTipText(Bundle.getMessage("DeleteMessageComboboxTip"));
189
190        // Manifest panel
191        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
192        pManifest.setLayout(new BoxLayout(pManifest, BoxLayout.Y_AXIS));
193        JScrollPane pManifestPane = new JScrollPane(pManifest);
194        pManifestPane.setBorder(BorderFactory.createTitledBorder(""));
195
196        // row 1 font type, size, format, orientation, text colors
197        JPanel p1 = new JPanel();
198        p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
199
200        JPanel pFont = new JPanel();
201        pFont.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFont")));
202        pFont.add(fontComboBox);
203
204        JPanel pFontSize = new JPanel();
205        pFontSize.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFontSize")));
206        pFontSize.add(fontSizeComboBox);
207
208        JPanel pFormat = new JPanel();
209        pFormat.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutFormat")));
210        pFormat.add(tabFormatCheckBox);
211        pFormat.add(manifestFormatComboBox);
212
213        JPanel pOrientation = new JPanel();
214        pOrientation.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutOrientation")));
215        pOrientation.add(manifestOrientationComboBox);
216
217        JPanel pDuplex = new JPanel();
218        pDuplex.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDuplex")));
219        pDuplex.add(printDuplexComboBox);
220
221        loadDuplexSidesComboBox();
222
223        p1.add(pFont);
224        p1.add(pFontSize);
225        p1.add(pFormat);
226        p1.add(pOrientation);
227        p1.add(pDuplex);
228
229        JPanel pColor = new JPanel();
230        pColor.setLayout(new BoxLayout(pColor, BoxLayout.X_AXIS));
231        pColor.add(
232                getColorChooserPanel(Bundle.getMessage("BorderLayoutPickupEngineColor"), Setup.getPickupEngineColor(),
233                        pickupEngineColorChooser, null));
234        pColor.add(getColorChooserPanel(Bundle.getMessage("BorderLayoutDropEngineColor"), Setup.getDropEngineColor(),
235                dropEngineColorChooser, null));
236        pColor.add(getColorChooserPanel(Bundle.getMessage("BorderLayoutPickupColor"), Setup.getPickupColor(),
237                pickupColorChooser, null));
238        pColor.add(getColorChooserPanel(Bundle.getMessage("BorderLayoutDropColor"), Setup.getDropColor(),
239                dropColorChooser, null));
240        pColor.add(getColorChooserPanel(Bundle.getMessage("BorderLayoutLocalColor"), Setup.getLocalColor(),
241                localColorChooser, null));
242
243        // load all of the message combo boxes, rows 2 through 5
244        loadFormatComboBox();
245
246        // Optional Switch List Panel
247        JPanel pSl = new JPanel();
248        pSl.setLayout(new BoxLayout(pSl, BoxLayout.X_AXIS));
249
250        JPanel pSwitchFormat = new JPanel();
251        pSwitchFormat.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListFormat")));
252        pSwitchFormat.add(formatSwitchListCheckBox);
253
254        pSwitchListOrientation
255                .setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListOrientation")));
256        pSwitchListOrientation.add(switchListOrientationComboBox);
257
258        pSl.add(pSwitchFormat);
259        pSl.add(pSwitchListOrientation);
260
261        JPanel pM = new JPanel();
262        pM.setLayout(new BoxLayout(pM, BoxLayout.X_AXIS));
263
264        // Switch List options
265        JPanel pSwitchOptions = new JPanel();
266        pSwitchOptions.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListOptions")));
267        pSwitchOptions.add(trackSummaryCheckBox);
268        pSwitchOptions.add(routeLocationCheckBox);
269        pSwitchOptions.add(switchListDepartureTimeCheckBox);
270
271        // Manifest options
272        JPanel pManifestOptions = new JPanel();
273        pManifestOptions.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutManifestOptions")));
274        pManifestOptions.add(printLocCommentsCheckBox);
275        pManifestOptions.add(printRouteCommentsCheckBox);
276        pManifestOptions.add(manifestDepartureTimeCheckBox);
277        pManifestOptions.add(truncateCheckBox);
278
279        pM.add(pSwitchOptions);
280        pM.add(pManifestOptions);
281
282        // Manifest and Switch List options
283        JPanel pManifestSwtichListOptions = new JPanel();
284        pManifestSwtichListOptions.setLayout(new GridBagLayout());
285        pManifestSwtichListOptions.setBorder(
286                BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutManifestSwitchListOptions")));
287        addItemLeft(pManifestSwtichListOptions, printValidCheckBox, 0, 0);
288        addItemLeft(pManifestSwtichListOptions, printLoadsEmptiesCheckBox, 1, 0);
289        addItemLeft(pManifestSwtichListOptions, groupCarMovesCheckBox, 2, 0);
290        addItemLeft(pManifestSwtichListOptions, printLocoLastCheckBox, 3, 0);
291        addItemLeft(pManifestSwtichListOptions, printCabooseLoadCheckBox, 4, 0);
292        addItemLeft(pManifestSwtichListOptions, printPassengerLoadCheckBox, 5, 0);
293
294        addItemLeft(pManifestSwtichListOptions, use12hrFormatCheckBox, 0, 1);
295        addItemLeft(pManifestSwtichListOptions, printTrainScheduleNameCheckBox, 1, 1);
296        addItemLeft(pManifestSwtichListOptions, sortByTrackCheckBox, 2, 1);
297        addItemLeft(pManifestSwtichListOptions, noPageBreaksCheckBox, 3, 1);
298        addItemLeft(pManifestSwtichListOptions, printHeadersCheckBox, 4, 1);
299        addItemLeft(pManifestSwtichListOptions, printPageHeaderCheckBox, 5, 1);
300
301        JPanel p2 = new JPanel();
302        p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
303
304        // Use text editor for manifest
305        JPanel pEdit = new JPanel();
306        pEdit.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutManifestPreview")));
307        pEdit.add(editManifestCheckBox);
308
309        // manifest logo
310        JPanel pLogo = new JPanel();
311        pLogo.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLogo")));
312        pLogo.add(removeLogoButton);
313        pLogo.add(addLogoButton);
314        pLogo.add(logoURL);
315
316        // Hazardous comment
317        JPanel pHazardous = new JPanel();
318        pHazardous.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutHazardous")));
319        pHazardous.add(hazardousTextField);
320
321        p2.add(pEdit);
322        p2.add(pLogo);
323        p2.add(pHazardous);
324
325        // missing cars comment
326        JPanel pCommentMia = new JPanel();
327        pCommentMia.setLayout(new GridBagLayout());
328        pCommentMia.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutCommentOptions")));
329        addItem(pCommentMia, commentScroller, 0, 0);
330        addItem(pCommentMia, getColorChooserPanel(Setup.getMiaComment(), missingCarColorChooser, boldCheckBox), 2, 0);
331
332        pManifest.add(p1);
333        pManifest.add(pColor);
334        pManifest.add(pEngPickup);
335        pManifest.add(pEngDrop);
336        pManifest.add(pPickup);
337        pManifest.add(pDrop);
338        pManifest.add(pLocal);
339        pManifest.add(pSl);
340        pManifest.add(pSwPickup);
341        pManifest.add(pSwDrop);
342        pManifest.add(pSwLocal);
343        pManifest.add(pM);
344        pManifest.add(pManifestSwtichListOptions);
345        pManifest.add(p2);
346        pManifest.add(pCommentMia);
347        pManifest.add(pMia);
348
349        // row 11
350        JPanel pControl = new JPanel();
351        pControl.setBorder(BorderFactory.createTitledBorder(""));
352        pControl.setLayout(new GridBagLayout());
353        addItem(pControl, saveButton, 0, 0);
354
355        add(pManifestPane);
356        add(pControl);
357
358        manifestFormatComboBox.setSelectedItem(Setup.getManifestFormat());
359        manifestOrientationComboBox.setSelectedItem(Setup.getManifestOrientation());
360        switchListOrientationComboBox.setSelectedItem(Setup.getSwitchListOrientation());
361
362        tabFormatCheckBox.setSelected(Setup.isTabEnabled());
363        printDuplexComboBox.setSelectedItem(Setup.getPrintDuplexSides());
364
365        formatSwitchListCheckBox.setSelected(Setup.isSwitchListFormatSameAsManifest());
366        printLocCommentsCheckBox.setSelected(Setup.isPrintLocationCommentsEnabled());
367        printRouteCommentsCheckBox.setSelected(Setup.isPrintRouteCommentsEnabled());
368        printLoadsEmptiesCheckBox.setSelected(Setup.isPrintLoadsAndEmptiesEnabled());
369        printCabooseLoadCheckBox.setSelected(Setup.isPrintCabooseLoadEnabled());
370        printPassengerLoadCheckBox.setSelected(Setup.isPrintPassengerLoadEnabled());
371        printTrainScheduleNameCheckBox.setSelected(Setup.isPrintTrainScheduleNameEnabled());
372        use12hrFormatCheckBox.setSelected(Setup.is12hrFormatEnabled());
373        printValidCheckBox.setSelected(Setup.isPrintValidEnabled());
374        sortByTrackCheckBox.setSelected(Setup.isSortByTrackNameEnabled());
375        noPageBreaksCheckBox.setSelected(Setup.isPrintNoPageBreaksEnabled());
376        printPageHeaderCheckBox.setSelected(Setup.isPrintPageHeaderEnabled());
377        printHeadersCheckBox.setSelected(Setup.isPrintHeadersEnabled());
378        truncateCheckBox.setSelected(Setup.isPrintTruncateManifestEnabled());
379        manifestDepartureTimeCheckBox.setSelected(Setup.isUseDepartureTimeEnabled());
380        trackSummaryCheckBox.setSelected(Setup.isPrintTrackSummaryEnabled());
381        trackSummaryCheckBox.setEnabled(Setup.isSwitchListRealTime());
382        routeLocationCheckBox.setSelected(Setup.isSwitchListRouteLocationCommentEnabled());
383        switchListDepartureTimeCheckBox.setSelected(Setup.isUseSwitchListDepartureTimeEnabled());
384        editManifestCheckBox.setSelected(Setup.isManifestEditorEnabled());
385        groupCarMovesCheckBox.setSelected(Setup.isGroupCarMovesEnabled());
386        printLocoLastCheckBox.setSelected(Setup.isPrintLocoLastEnabled());
387
388        miaCommentTextArea.setText(TrainCommon.getOnlyText(Setup.getMiaComment()));
389        hazardousTextField.setText(Setup.getHazardousMsg());
390
391        setSwitchListVisible(!formatSwitchListCheckBox.isSelected());
392
393        updateLogoButtons();
394
395        loadFontSizeComboBox();
396        loadFontComboBox();
397
398        // setup buttons
399        addButtonAction(addLogoButton);
400        addButtonAction(removeLogoButton);
401        addButtonAction(saveButton);
402
403        addButtonAction(addEngPickupComboboxButton);
404        addButtonAction(deleteEngPickupComboboxButton);
405        addButtonAction(addEngDropComboboxButton);
406        addButtonAction(deleteEngDropComboboxButton);
407
408        addButtonAction(addCarPickupComboboxButton);
409        addButtonAction(deleteCarPickupComboboxButton);
410        addButtonAction(addCarDropComboboxButton);
411        addButtonAction(deleteCarDropComboboxButton);
412        addButtonAction(addLocalComboboxButton);
413        addButtonAction(deleteLocalComboboxButton);
414
415        addButtonAction(addSwitchListPickupComboboxButton);
416        addButtonAction(deleteSwitchListPickupComboboxButton);
417        addButtonAction(addSwitchListDropComboboxButton);
418        addButtonAction(deleteSwitchListDropComboboxButton);
419        addButtonAction(addSwitchListLocalComboboxButton);
420        addButtonAction(deleteSwitchListLocalComboboxButton);
421        
422        addButtonAction(addMiaComboboxButton);
423        addButtonAction(deleteMiaComboboxButton);
424
425        addCheckBoxAction(tabFormatCheckBox);
426        addCheckBoxAction(formatSwitchListCheckBox);
427        addCheckBoxAction(truncateCheckBox);
428
429        addComboBoxAction(manifestFormatComboBox);
430
431        Setup.getDefault().addPropertyChangeListener(this);
432    }
433
434    // Add Remove Logo and Save buttons
435    @Override
436    public void buttonActionPerformed(java.awt.event.ActionEvent ae) {
437        if (ae.getSource() == addLogoButton) {
438            log.debug("add logo button pressed");
439            File f = selectFile();
440            if (f != null) {
441                Setup.setManifestLogoURL(FileUtil.getPortableFilename(f));
442            }
443            updateLogoButtons();
444        }
445        if (ae.getSource() == removeLogoButton) {
446            log.debug("remove logo button pressed");
447            Setup.setManifestLogoURL("");
448            updateLogoButtons();
449        }
450        // add or delete message comboBox
451        if (ae.getSource() == addEngPickupComboboxButton) {
452            addComboBox(pEngPickup, enginePickupMessageList, Setup.getEngineMessageComboBox());
453        }
454        if (ae.getSource() == deleteEngPickupComboboxButton) {
455            removeComboBox(pEngPickup, enginePickupMessageList);
456        }
457        if (ae.getSource() == addEngDropComboboxButton) {
458            addComboBox(pEngDrop, engineDropMessageList, Setup.getEngineMessageComboBox());
459        }
460        if (ae.getSource() == deleteEngDropComboboxButton) {
461            removeComboBox(pEngDrop, engineDropMessageList);
462        }
463
464        if (ae.getSource() == addCarPickupComboboxButton) {
465            addComboBox(pPickup, carPickupMessageList, Setup.getCarMessageComboBox());
466        }
467        if (ae.getSource() == deleteCarPickupComboboxButton) {
468            removeComboBox(pPickup, carPickupMessageList);
469        }
470        if (ae.getSource() == addCarDropComboboxButton) {
471            addComboBox(pDrop, carDropMessageList, Setup.getCarMessageComboBox());
472        }
473        if (ae.getSource() == deleteCarDropComboboxButton) {
474            removeComboBox(pDrop, carDropMessageList);
475        }
476
477        if (ae.getSource() == addLocalComboboxButton) {
478            addComboBox(pLocal, localMessageList, Setup.getCarMessageComboBox());
479        }
480        if (ae.getSource() == deleteLocalComboboxButton) {
481            removeComboBox(pLocal, localMessageList);
482        }
483
484        if (ae.getSource() == addSwitchListPickupComboboxButton) {
485            addComboBox(pSwPickup, switchListCarPickupMessageList, Setup.getCarMessageComboBox());
486        }
487        if (ae.getSource() == deleteSwitchListPickupComboboxButton) {
488            removeComboBox(pSwPickup, switchListCarPickupMessageList);
489        }
490        if (ae.getSource() == addSwitchListDropComboboxButton) {
491            addComboBox(pSwDrop, switchListCarDropMessageList, Setup.getCarMessageComboBox());
492        }
493        if (ae.getSource() == deleteSwitchListDropComboboxButton) {
494            removeComboBox(pSwDrop, switchListCarDropMessageList);
495        }
496
497        if (ae.getSource() == addSwitchListLocalComboboxButton) {
498            addComboBox(pSwLocal, switchListLocalMessageList, Setup.getCarMessageComboBox());
499        }
500        if (ae.getSource() == deleteSwitchListLocalComboboxButton) {
501            removeComboBox(pSwLocal, switchListLocalMessageList);
502        }
503        
504        if (ae.getSource() == addMiaComboboxButton) {
505            addComboBox(pMia, miaMessageList, Setup.getCarMessageComboBox());
506        }
507        if (ae.getSource() == deleteMiaComboboxButton) {
508            removeComboBox(pMia, miaMessageList);
509        }
510
511        if (ae.getSource() == saveButton) {
512            this.savePreferences();
513            var topLevelAncestor = getTopLevelAncestor();
514            if (Setup.isCloseWindowOnSaveEnabled() && topLevelAncestor instanceof PrintOptionFrame) {
515                ((PrintOptionFrame) topLevelAncestor).dispose();
516            }
517        }
518    }
519
520    @Override
521    public void checkBoxActionPerformed(ActionEvent ae) {
522        if (ae.getSource() == tabFormatCheckBox) {
523            loadFontComboBox();
524        }
525        if (ae.getSource() == formatSwitchListCheckBox) {
526            log.debug("Switch list check box activated");
527            setSwitchListVisible(!formatSwitchListCheckBox.isSelected());
528            setPreferredSize(null);
529            var topLevelAncestor = getTopLevelAncestor();
530            if (topLevelAncestor instanceof PrintOptionFrame) {
531                ((PrintOptionFrame) topLevelAncestor).pack();
532            }
533        }
534        if (ae.getSource() == truncateCheckBox && truncateCheckBox.isSelected()) {
535            if (JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("EnableTruncateWarning"),
536                    Bundle.getMessage("TruncateManifests?"),
537                    JmriJOptionPane.YES_NO_OPTION) == JmriJOptionPane.NO_OPTION) {
538                truncateCheckBox.setSelected(false);
539            }
540        }
541    }
542
543    @Override
544    public void comboBoxActionPerformed(ActionEvent ae) {
545        if (ae.getSource() == manifestFormatComboBox) {
546            loadFontComboBox();
547        }
548    }
549
550    private void setSwitchListVisible(boolean b) {
551        pSwitchListOrientation.setVisible(b);
552        pSwPickup.setVisible(b);
553        pSwDrop.setVisible(b);
554        pSwLocal.setVisible(b);
555    }
556
557    /**
558     * We always use the same file chooser in this class, so that the user's
559     * last-accessed directory remains available.
560     */
561    JFileChooser fc = jmri.jmrit.XmlFile.userFileChooser(Bundle.getMessage("Images"));
562
563    private File selectFile() {
564        if (fc == null) {
565            log.error("Could not find user directory");
566        } else {
567            fc.setDialogTitle(Bundle.getMessage("FindDesiredImage"));
568            // when reusing the chooser, make sure new files are included
569            fc.rescanCurrentDirectory();
570            int retVal = fc.showOpenDialog(null);
571            // handle selection or cancel
572            if (retVal == JFileChooser.APPROVE_OPTION) {
573                return fc.getSelectedFile();
574            }
575        }
576        return null;
577    }
578
579    private void updateLogoButtons() {
580        boolean flag = Setup.getManifestLogoURL().equals(Setup.NONE);
581        addLogoButton.setVisible(flag);
582        removeLogoButton.setVisible(!flag);
583        logoURL.setText(Setup.getManifestLogoURL());
584        var topLevelAncestor = getTopLevelAncestor();
585        if (topLevelAncestor instanceof PrintOptionFrame) {
586            ((PrintOptionFrame) topLevelAncestor).pack();
587        }
588    }
589
590    /*
591     * Creates a dialog to select where to place a new message box
592     */
593    private void addComboBox(JPanel panel, List<JComboBox<String>> list, JComboBox<String> box) {
594        final JDialog dialog = new JDialog();
595        dialog.setLayout(new BorderLayout());
596        dialog.setTitle(Bundle.getMessage("AddMessageComboboxTip"));
597        dialog.setSize(600, 600);
598        
599        JPanel radioPane = new JPanel();
600        radioPane.setLayout(new FlowLayout(FlowLayout.CENTER));
601        dialog.add(radioPane, BorderLayout.NORTH);
602        
603        JRadioButton start = new JRadioButton(Bundle.getMessage("Start"));
604        JRadioButton middle = new JRadioButton(Bundle.getMessage("Middle"));
605        JRadioButton end = new JRadioButton(Bundle.getMessage("End"));
606        
607        ButtonGroup group = new ButtonGroup();
608        group.add(start);
609        group.add(middle);
610        group.add(end);
611        
612        radioPane.add(start);
613        radioPane.add(middle);
614        radioPane.add(end);
615        
616        end.setSelected(true);
617        
618        JPanel indexPane = new JPanel();
619        indexPane.setLayout(new FlowLayout(FlowLayout.CENTER));
620        dialog.add(indexPane);
621        
622        JSpinner spinIndex = new JSpinner(new SpinnerNumberModel(list.size(), 0, list.size(), 1));
623        indexPane.add(spinIndex);
624             
625        start.addActionListener(new ActionListener() {
626            @Override
627            public void actionPerformed(ActionEvent arg0) {
628                spinIndex.setValue(0);
629            }
630        });
631        
632        middle.addActionListener(new ActionListener() {
633            @Override
634            public void actionPerformed(ActionEvent arg0) {
635                spinIndex.setValue(list.size()/2);
636            }
637        });
638        
639        end.addActionListener(new ActionListener() {
640            @Override
641            public void actionPerformed(ActionEvent arg0) {
642                spinIndex.setValue(list.size());
643            }
644        });
645
646        JPanel buttonPane = new JPanel();
647        buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
648        dialog.add(buttonPane, BorderLayout.SOUTH);
649
650        JButton okayButton = new JButton(Bundle.getMessage("ButtonOK"));
651        okayButton.addActionListener(new ActionListener() {
652            @Override
653            public void actionPerformed(ActionEvent arg0) {
654                int index = (int) spinIndex.getValue();
655                list.add(index, box);
656                panel.add(box, index + 1);
657                panel.revalidate();
658                pManifest.revalidate();
659                dialog.dispose();
660                return;
661            }
662        });
663        buttonPane.add(okayButton);
664
665        JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel"));
666        cancelButton.addActionListener(new ActionListener() {
667            @Override
668            public void actionPerformed(ActionEvent arg0) {
669                dialog.dispose();
670                return;
671            }
672        });
673        buttonPane.add(cancelButton);
674
675        dialog.setModal(true);
676        dialog.pack();
677        dialog.setSize(2 * dialog.getWidth(), dialog.getHeight());
678        dialog.setLocationRelativeTo(this);
679        dialog.setVisible(true);
680    }
681
682
683    private void removeComboBox(JPanel panel, List<JComboBox<String>> list) {
684        for (int i = 0; i < list.size(); i++) {
685            JComboBox<String> cb = list.get(i);
686            if (cb.getSelectedItem().equals(Setup.BLANK)) {
687                list.remove(i);
688                panel.remove(cb);
689                panel.revalidate();
690                pManifest.revalidate();
691                return;
692            }
693        }
694    }
695
696    private void loadFormatComboBox() {
697        // loco pick up message format
698        pEngPickup.removeAll();
699        enginePickupMessageList.clear();
700        pEngPickup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPickupEngine")));
701        pEngPickup.add(pickupEngPrefix);
702        pickupEngPrefix.setText(Setup.getPickupEnginePrefix());
703        String[] format = Setup.getPickupEngineMessageFormat();
704        for (String f : format) {
705            JComboBox<String> cb = Setup.getEngineMessageComboBox();
706            cb.setSelectedItem(f);
707            pEngPickup.add(cb);
708            enginePickupMessageList.add(cb);
709        }
710        pEngPickup.add(addEngPickupComboboxButton);
711        pEngPickup.add(deleteEngPickupComboboxButton);
712        pEngPickup.revalidate();
713
714        // loco set out message format
715        pEngDrop.removeAll();
716        engineDropMessageList.clear();
717        pEngDrop.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDropEngine")));
718        pEngDrop.add(dropEngPrefix);
719        dropEngPrefix.setText(Setup.getDropEnginePrefix());
720        format = Setup.getDropEngineMessageFormat();
721        for (String f : format) {
722            JComboBox<String> cb = Setup.getEngineMessageComboBox();
723            cb.setSelectedItem(f);
724            pEngDrop.add(cb);
725            engineDropMessageList.add(cb);
726        }
727        pEngDrop.add(addEngDropComboboxButton);
728        pEngDrop.add(deleteEngDropComboboxButton);
729        pEngDrop.revalidate();
730
731        // car pickup message format
732        pPickup.removeAll();
733        carPickupMessageList.clear();
734        pPickup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutPickupCar")));
735        pPickup.add(pickupCarPrefix);
736        pickupCarPrefix.setText(Setup.getPickupCarPrefix());
737        String[] pickFormat = Setup.getPickupManifestMessageFormat();
738        for (String pf : pickFormat) {
739            JComboBox<String> cb = Setup.getCarMessageComboBox();
740            cb.setSelectedItem(pf);
741            pPickup.add(cb);
742            carPickupMessageList.add(cb);
743        }
744        pPickup.add(addCarPickupComboboxButton);
745        pPickup.add(deleteCarPickupComboboxButton);
746        pPickup.revalidate();
747
748        // car drop message format
749        pDrop.removeAll();
750        carDropMessageList.clear();
751        pDrop.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDropCar")));
752        pDrop.add(dropCarPrefix);
753        dropCarPrefix.setText(Setup.getDropCarPrefix());
754        String[] dropFormat = Setup.getDropManifestMessageFormat();
755        for (String lf : dropFormat) {
756            JComboBox<String> cb = Setup.getCarMessageComboBox();
757            cb.setSelectedItem(lf);
758            pDrop.add(cb);
759            carDropMessageList.add(cb);
760        }
761        pDrop.add(addCarDropComboboxButton);
762        pDrop.add(deleteCarDropComboboxButton);
763        pDrop.revalidate();
764
765        // local car move message format
766        pLocal.removeAll();
767        localMessageList.clear();
768        pLocal.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutLocal")));
769        pLocal.add(localPrefix);
770        localPrefix.setText(Setup.getLocalPrefix());
771        String[] localFormat = Setup.getLocalManifestMessageFormat();
772        for (String lf : localFormat) {
773            JComboBox<String> cb = Setup.getCarMessageComboBox();
774            cb.setSelectedItem(lf);
775            pLocal.add(cb);
776            localMessageList.add(cb);
777        }
778        pLocal.add(addLocalComboboxButton);
779        pLocal.add(deleteLocalComboboxButton);
780        pLocal.revalidate();
781
782        // switch list car pickup message format
783        pSwPickup.removeAll();
784        switchListCarPickupMessageList.clear();
785        pSwPickup.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListPickupCar")));
786        pSwPickup.add(switchListPickupCarPrefix);
787        switchListPickupCarPrefix.setText(Setup.getSwitchListPickupCarPrefix());
788        pickFormat = Setup.getPickupSwitchListMessageFormat();
789        for (String pf : pickFormat) {
790            JComboBox<String> cb = Setup.getCarMessageComboBox();
791            cb.setSelectedItem(pf);
792            pSwPickup.add(cb);
793            switchListCarPickupMessageList.add(cb);
794        }
795        pSwPickup.add(addSwitchListPickupComboboxButton);
796        pSwPickup.add(deleteSwitchListPickupComboboxButton);
797
798        // switch list car drop message format
799        pSwDrop.removeAll();
800        switchListCarDropMessageList.clear();
801        pSwDrop.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListDropCar")));
802        pSwDrop.add(switchListDropCarPrefix);
803        switchListDropCarPrefix.setText(Setup.getSwitchListDropCarPrefix());
804        dropFormat = Setup.getDropSwitchListMessageFormat();
805        for (String df : dropFormat) {
806            JComboBox<String> cb = Setup.getCarMessageComboBox();
807            cb.setSelectedItem(df);
808            pSwDrop.add(cb);
809            switchListCarDropMessageList.add(cb);
810        }
811        pSwDrop.add(addSwitchListDropComboboxButton);
812        pSwDrop.add(deleteSwitchListDropComboboxButton);
813
814        // switch list local car move message format
815        pSwLocal.removeAll();
816        switchListLocalMessageList.clear();
817        pSwLocal.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutSwitchListLocal")));
818        pSwLocal.add(switchListLocalPrefix);
819        switchListLocalPrefix.setText(Setup.getSwitchListLocalPrefix());
820        localFormat = Setup.getLocalSwitchListMessageFormat();
821        for (String lf : localFormat) {
822            JComboBox<String> cb = Setup.getCarMessageComboBox();
823            cb.setSelectedItem(lf);
824            pSwLocal.add(cb);
825            switchListLocalMessageList.add(cb);
826        }
827        pSwLocal.add(addSwitchListLocalComboboxButton);
828        pSwLocal.add(deleteSwitchListLocalComboboxButton);
829        
830        // MIA message format
831        pMia.removeAll();
832        pMia.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutMisplacedCar")));
833        miaMessageList.clear();
834        String[] miaFormat = Setup.getMissingCarMessageFormat();
835        // dummy entry so add/delete ComboBox works correctly
836        pMia.add(new JLabel(" "));
837        for (String f : miaFormat) {
838            JComboBox<String> cb = Setup.getCarMessageComboBox();
839            cb.setSelectedItem(f);
840            pMia.add(cb);
841            miaMessageList.add(cb);
842        }
843        pMia.add(addMiaComboboxButton);
844        pMia.add(deleteMiaComboboxButton);
845    }
846
847    private void loadFontSizeComboBox() {
848        loadFontSizeComboBox(fontSizeComboBox);
849        fontSizeComboBox.setSelectedItem(Setup.getManifestFontSize());
850    }
851
852    private void loadFontComboBox() {
853        fontComboBox.removeAllItems();
854        List<String> fonts = FontComboUtil.getFonts(FontComboUtil.ALL);
855        if (tabFormatCheckBox.isSelected() || !manifestFormatComboBox.getSelectedItem().equals(Setup.STANDARD_FORMAT)) {
856            fonts = FontComboUtil.getFonts(FontComboUtil.MONOSPACED);
857        }
858        for (String font : fonts) {
859            fontComboBox.addItem(font);
860        }
861        fontComboBox.setSelectedItem(Setup.getFontName());
862    }
863
864    private void loadDuplexSidesComboBox() {
865        printDuplexComboBox.addItem(Sides.ONE_SIDED);
866        printDuplexComboBox.addItem(Sides.TWO_SIDED_LONG_EDGE);
867        printDuplexComboBox.addItem(Sides.TWO_SIDED_SHORT_EDGE);
868        OperationsPanel.padComboBox(printDuplexComboBox, Sides.TWO_SIDED_SHORT_EDGE.toString().length());
869    }
870
871    @Override
872    public String getTabbedPreferencesTitle() {
873        return Bundle.getMessage("TitlePrintOptions");
874    }
875
876    @Override
877    public String getPreferencesTooltip() {
878        return null;
879    }
880
881    @Override
882    public void savePreferences() {
883        // font name
884        Setup.setFontName((String) fontComboBox.getSelectedItem());
885        // font size
886        Setup.setManifestFontSize((Integer) fontSizeComboBox.getSelectedItem());
887        // page orientation
888        Setup.setManifestOrientation((String) manifestOrientationComboBox.getSelectedItem());
889        Setup.setSwitchListOrientation((String) switchListOrientationComboBox.getSelectedItem());
890        Setup.setPrintDuplexSides((Sides) printDuplexComboBox.getSelectedItem());
891        // format
892        Setup.setManifestFormat((String) manifestFormatComboBox.getSelectedItem());
893        // drop and pick up color option
894        Setup.setDropEngineColor(dropEngineColorChooser.getColor());
895        Setup.setPickupEngineColor(pickupEngineColorChooser.getColor());
896        Setup.setDropColor(dropColorChooser.getColor());
897        Setup.setPickupColor(pickupColorChooser.getColor());
898        Setup.setLocalColor(localColorChooser.getColor());
899        // save engine pick up message format
900        Setup.setPickupEnginePrefix(pickupEngPrefix.getText());
901        String[] format = new String[enginePickupMessageList.size()];
902        for (int i = 0; i < enginePickupMessageList.size(); i++) {
903            JComboBox<?> cb = enginePickupMessageList.get(i);
904            format[i] = (String) cb.getSelectedItem();
905        }
906        Setup.setPickupEngineMessageFormat(format);
907        // save engine drop message format
908        Setup.setDropEnginePrefix(dropEngPrefix.getText());
909        format = new String[engineDropMessageList.size()];
910        for (int i = 0; i < engineDropMessageList.size(); i++) {
911            JComboBox<?> cb = engineDropMessageList.get(i);
912            format[i] = (String) cb.getSelectedItem();
913        }
914        Setup.setDropEngineMessageFormat(format);
915        // save car pick up message format
916        Setup.setPickupCarPrefix(pickupCarPrefix.getText());
917        format = new String[carPickupMessageList.size()];
918        for (int i = 0; i < carPickupMessageList.size(); i++) {
919            JComboBox<?> cb = carPickupMessageList.get(i);
920            format[i] = (String) cb.getSelectedItem();
921        }
922        Setup.setPickupManifestMessageFormat(format);
923        // save car drop message format
924        Setup.setDropCarPrefix(dropCarPrefix.getText());
925        format = new String[carDropMessageList.size()];
926        for (int i = 0; i < carDropMessageList.size(); i++) {
927            JComboBox<?> cb = carDropMessageList.get(i);
928            format[i] = (String) cb.getSelectedItem();
929        }
930        Setup.setDropManifestMessageFormat(format);
931        // save local message format
932        Setup.setLocalPrefix(localPrefix.getText());
933        format = new String[localMessageList.size()];
934        for (int i = 0; i < localMessageList.size(); i++) {
935            JComboBox<?> cb = localMessageList.get(i);
936            format[i] = (String) cb.getSelectedItem();
937        }
938        Setup.setLocalManifestMessageFormat(format);
939        // save switch list car pick up message format
940        Setup.setSwitchListPickupCarPrefix(switchListPickupCarPrefix.getText());
941        format = new String[switchListCarPickupMessageList.size()];
942        for (int i = 0; i < switchListCarPickupMessageList.size(); i++) {
943            JComboBox<?> cb = switchListCarPickupMessageList.get(i);
944            format[i] = (String) cb.getSelectedItem();
945        }
946        Setup.setPickupSwitchListMessageFormat(format);
947        // save switch list car drop message format
948        Setup.setSwitchListDropCarPrefix(switchListDropCarPrefix.getText());
949        format = new String[switchListCarDropMessageList.size()];
950        for (int i = 0; i < switchListCarDropMessageList.size(); i++) {
951            JComboBox<?> cb = switchListCarDropMessageList.get(i);
952            format[i] = (String) cb.getSelectedItem();
953        }
954        Setup.setDropSwitchListMessageFormat(format);
955        // save switch list local message format
956        Setup.setSwitchListLocalPrefix(switchListLocalPrefix.getText());
957        format = new String[switchListLocalMessageList.size()];
958        for (int i = 0; i < switchListLocalMessageList.size(); i++) {
959            JComboBox<?> cb = switchListLocalMessageList.get(i);
960            format[i] = (String) cb.getSelectedItem();
961        }
962        Setup.setLocalSwitchListMessageFormat(format);
963        // save MIA message format
964        format = new String[miaMessageList.size()];
965        for (int i = 0; i < miaMessageList.size(); i++) {
966            JComboBox<?> cb = miaMessageList.get(i);
967            format[i] = (String) cb.getSelectedItem();
968        }
969        Setup.setMissingCarMessageFormat(format);
970        // hazardous comment
971        Setup.setHazardousMsg(hazardousTextField.getText());
972        // misplaced car comment
973        Setup.setMiaComment(
974                TrainCommon.formatColorString(miaCommentTextArea.getText(), missingCarColorChooser.getColor(),
975                        boldCheckBox.isSelected()));
976        Setup.setSwitchListFormatSameAsManifest(formatSwitchListCheckBox.isSelected());
977        Setup.setPrintLocationCommentsEnabled(printLocCommentsCheckBox.isSelected());
978        Setup.setPrintRouteCommentsEnabled(printRouteCommentsCheckBox.isSelected());
979        Setup.setPrintLoadsAndEmptiesEnabled(printLoadsEmptiesCheckBox.isSelected());
980        Setup.setPrintCabooseLoadEnabled(printCabooseLoadCheckBox.isSelected());
981        Setup.setPrintPassengerLoadEnabled(printPassengerLoadCheckBox.isSelected());
982        Setup.set12hrFormatEnabled(use12hrFormatCheckBox.isSelected());
983        Setup.setPrintValidEnabled(printValidCheckBox.isSelected());
984        Setup.setSortByTrackNameEnabled(sortByTrackCheckBox.isSelected());
985        Setup.setPrintNoPageBreaksEnabled(noPageBreaksCheckBox.isSelected());
986        Setup.setPrintPageHeaderEnabled(printPageHeaderCheckBox.isSelected());
987        Setup.setPrintHeadersEnabled(printHeadersCheckBox.isSelected());
988        Setup.setPrintTrainScheduleNameEnabled(printTrainScheduleNameCheckBox.isSelected());
989        Setup.setPrintTruncateManifestEnabled(truncateCheckBox.isSelected());
990        Setup.setUseDepartureTimeEnabled(manifestDepartureTimeCheckBox.isSelected());
991        Setup.setManifestEditorEnabled(editManifestCheckBox.isSelected());
992        Setup.setPrintTrackSummaryEnabled(trackSummaryCheckBox.isSelected());
993        Setup.setUseSwitchListDepartureTimeEnabled(switchListDepartureTimeCheckBox.isSelected());
994        Setup.setSwitchListRouteLocationCommentEnabled(routeLocationCheckBox.isSelected());
995        Setup.setGroupCarMoves(groupCarMovesCheckBox.isSelected());
996        Setup.setPrintLocoLast(printLocoLastCheckBox.isSelected());
997
998        // reload combo boxes if tab changed
999        boolean oldTabEnabled = Setup.isTabEnabled();
1000        Setup.setTabEnabled(tabFormatCheckBox.isSelected());
1001        if (oldTabEnabled ^ Setup.isTabEnabled()) {
1002            loadFormatComboBox();
1003        }
1004
1005        // recreate all train manifests
1006        InstanceManager.getDefault(TrainManager.class).setTrainsModified();
1007
1008        InstanceManager.getDefault(OperationsSetupXml.class).writeOperationsFile();
1009    }
1010
1011    @Override
1012    public boolean isDirty() {
1013        if (!Setup.getFontName().equals(fontComboBox.getSelectedItem()) ||
1014                Setup.getManifestFontSize() != (Integer) fontSizeComboBox.getSelectedItem() ||
1015                Setup.getPrintDuplexSides() != printDuplexComboBox.getSelectedItem() ||
1016                !Setup.getManifestOrientation().equals(manifestOrientationComboBox.getSelectedItem()) ||
1017                !Setup.getSwitchListOrientation().equals(switchListOrientationComboBox.getSelectedItem()) ||
1018                !Setup.getManifestFormat().equals(manifestFormatComboBox.getSelectedItem()) ||
1019                !Setup.getDropEngineColor().equals(dropEngineColorChooser.getColor()) ||
1020                !Setup.getPickupEngineColor().equals(pickupEngineColorChooser.getColor()) ||
1021                !Setup.getDropColor().equals(dropColorChooser.getColor()) ||
1022                !Setup.getPickupColor().equals(pickupColorChooser.getColor()) ||
1023                !Setup.getLocalColor().equals(localColorChooser.getColor()) ||
1024                !Setup.getHazardousMsg().equals(hazardousTextField.getText()) ||
1025                !Setup.getMiaComment()
1026                        .equals(TrainCommon.formatColorString(miaCommentTextArea.getText(),
1027                                missingCarColorChooser.getColor(), boldCheckBox.isSelected())) ||
1028                Setup.isSwitchListFormatSameAsManifest() != formatSwitchListCheckBox.isSelected() ||
1029                Setup.isPrintLocationCommentsEnabled() != printLocCommentsCheckBox.isSelected() ||
1030                Setup.isPrintRouteCommentsEnabled() != printRouteCommentsCheckBox.isSelected() ||
1031                Setup.isPrintLoadsAndEmptiesEnabled() != printLoadsEmptiesCheckBox.isSelected() ||
1032                Setup.isPrintCabooseLoadEnabled() != printCabooseLoadCheckBox.isSelected() ||
1033                Setup.isPrintPassengerLoadEnabled() != printPassengerLoadCheckBox.isSelected() ||
1034                Setup.is12hrFormatEnabled() != use12hrFormatCheckBox.isSelected() ||
1035                Setup.isPrintValidEnabled() != printValidCheckBox.isSelected() ||
1036                Setup.isSortByTrackNameEnabled() != sortByTrackCheckBox.isSelected() ||
1037                Setup.isPrintNoPageBreaksEnabled() != noPageBreaksCheckBox.isSelected() ||
1038                Setup.isPrintHeadersEnabled() != printHeadersCheckBox.isSelected() ||
1039                Setup.isPrintPageHeaderEnabled() != printPageHeaderCheckBox.isSelected() ||
1040                Setup.isPrintTrainScheduleNameEnabled() != printTrainScheduleNameCheckBox.isSelected() ||
1041                Setup.isPrintTruncateManifestEnabled() != truncateCheckBox.isSelected() ||
1042                Setup.isUseDepartureTimeEnabled() != manifestDepartureTimeCheckBox.isSelected() ||
1043                Setup.isManifestEditorEnabled() != editManifestCheckBox.isSelected() ||
1044                Setup.isSwitchListRouteLocationCommentEnabled() != routeLocationCheckBox.isSelected() ||
1045                Setup.isPrintTrackSummaryEnabled() != trackSummaryCheckBox.isSelected() ||
1046                Setup.isUseSwitchListDepartureTimeEnabled() != switchListDepartureTimeCheckBox.isSelected() ||
1047                Setup.isGroupCarMovesEnabled() != groupCarMovesCheckBox.isSelected() ||
1048                Setup.isPrintLocoLastEnabled() != printLocoLastCheckBox.isSelected() ||
1049                Setup.isTabEnabled() != tabFormatCheckBox.isSelected()) {
1050            return true;
1051        }
1052        // engine pick up message format
1053        String[] format = new String[enginePickupMessageList.size()];
1054        for (int i = 0; i < enginePickupMessageList.size(); i++) {
1055            JComboBox<?> cb = enginePickupMessageList.get(i);
1056            format[i] = (String) cb.getSelectedItem();
1057        }
1058        if (!Setup.getPickupEnginePrefix().equals(pickupEngPrefix.getText()) ||
1059                !Arrays.equals(Setup.getPickupEngineMessageFormat(), format)) {
1060            return true;
1061        }
1062        // engine drop message format
1063        format = new String[engineDropMessageList.size()];
1064        for (int i = 0; i < engineDropMessageList.size(); i++) {
1065            JComboBox<?> cb = engineDropMessageList.get(i);
1066            format[i] = (String) cb.getSelectedItem();
1067        }
1068        if (!Setup.getDropEnginePrefix().equals(dropEngPrefix.getText()) ||
1069                !Arrays.equals(Setup.getDropEngineMessageFormat(), format)) {
1070            return true;
1071        }
1072        // car pick up message format
1073        format = new String[carPickupMessageList.size()];
1074        for (int i = 0; i < carPickupMessageList.size(); i++) {
1075            JComboBox<?> cb = carPickupMessageList.get(i);
1076            format[i] = (String) cb.getSelectedItem();
1077        }
1078        if (!Setup.getPickupCarPrefix().equals(this.pickupCarPrefix.getText()) ||
1079                !Arrays.equals(Setup.getPickupManifestMessageFormat(), format)) {
1080            return true;
1081        }
1082        // car drop message format
1083        format = new String[carDropMessageList.size()];
1084        for (int i = 0; i < carDropMessageList.size(); i++) {
1085            JComboBox<?> cb = carDropMessageList.get(i);
1086            format[i] = (String) cb.getSelectedItem();
1087        }
1088        if (!Setup.getDropCarPrefix().equals(this.dropCarPrefix.getText()) ||
1089                !Arrays.equals(Setup.getDropManifestMessageFormat(), format)) {
1090            return true;
1091        }
1092        // local message format
1093        format = new String[localMessageList.size()];
1094        for (int i = 0; i < localMessageList.size(); i++) {
1095            JComboBox<?> cb = localMessageList.get(i);
1096            format[i] = (String) cb.getSelectedItem();
1097        }
1098        if (!Setup.getLocalPrefix().equals(this.localPrefix.getText()) ||
1099                !Arrays.equals(Setup.getLocalManifestMessageFormat(), format)) {
1100            return true;
1101        }
1102        // switch list car pick up message format
1103        format = new String[switchListCarPickupMessageList.size()];
1104        for (int i = 0; i < switchListCarPickupMessageList.size(); i++) {
1105            JComboBox<?> cb = switchListCarPickupMessageList.get(i);
1106            format[i] = (String) cb.getSelectedItem();
1107        }
1108        if (!Setup.getSwitchListPickupCarPrefix().equals(this.switchListPickupCarPrefix.getText()) ||
1109                !Arrays.equals(Setup.getPickupSwitchListMessageFormat(), format)) {
1110            return true;
1111        }
1112        // switch list car drop message format
1113        format = new String[switchListCarDropMessageList.size()];
1114        for (int i = 0; i < switchListCarDropMessageList.size(); i++) {
1115            JComboBox<?> cb = switchListCarDropMessageList.get(i);
1116            format[i] = (String) cb.getSelectedItem();
1117        }
1118        if (!Setup.getSwitchListDropCarPrefix().equals(this.switchListDropCarPrefix.getText()) ||
1119                !Arrays.equals(Setup.getDropSwitchListMessageFormat(), format)) {
1120            return true;
1121        }
1122        // switch list local message format
1123        format = new String[switchListLocalMessageList.size()];
1124        for (int i = 0; i < switchListLocalMessageList.size(); i++) {
1125            JComboBox<?> cb = switchListLocalMessageList.get(i);
1126            format[i] = (String) cb.getSelectedItem();
1127        }
1128        if (!Setup.getSwitchListLocalPrefix().equals(this.switchListLocalPrefix.getText()) ||
1129                !Arrays.equals(Setup.getLocalSwitchListMessageFormat(), format)) {
1130            return true;
1131        }
1132        // Mia message format
1133        format = new String[miaMessageList.size()];
1134        for (int i = 0; i < miaMessageList.size(); i++) {
1135            JComboBox<?> cb = miaMessageList.get(i);
1136            format[i] = (String) cb.getSelectedItem();
1137        }
1138        if (!Arrays.equals(Setup.getMissingCarMessageFormat(), format)) {
1139            return true;
1140        }
1141        return false;
1142    }
1143
1144    @Override
1145    public void propertyChange(java.beans.PropertyChangeEvent e) {
1146        if (Control.SHOW_PROPERTY) {
1147            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(),
1148                    e.getNewValue());
1149        }
1150        if (e.getPropertyName().equals(Setup.REAL_TIME_PROPERTY_CHANGE)) {
1151            trackSummaryCheckBox.setEnabled(Setup.isSwitchListRealTime());
1152        }
1153    }
1154
1155    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PrintOptionPanel.class);
1156
1157}