001package jmri.jmrix.can.cbus.swing.console;
002
003import java.awt.Color;
004import java.awt.Desktop;
005import java.io.File;
006import java.io.FileNotFoundException;
007import java.io.FileOutputStream;
008import java.io.IOException;
009import java.io.PrintStream;
010import javax.swing.*;
011import jmri.util.FileUtil;
012import jmri.util.swing.JmriJOptionPane;
013
014/**
015 * Pane for CBUS Console Logging to File Options
016 *
017 * @author Andrew Crosland Copyright (C) 2008
018 * @author Steve Young Copyright (C) 2018
019 */
020public class CbusConsoleLoggingPane extends javax.swing.JPanel {
021
022    private final CbusConsolePane _mainPane;
023    private final JFileChooser logFileChooser;
024    private final JToggleButton startStopLogButton;
025    private final JButton openLogFileButton;
026    private final JButton openFileChooserButton;
027    private final JTextField entryField;
028    private final JButton logenterButton;
029
030    // @SuppressFBWarnings(value = "IS2_INCONSISTENT_SYNC", justification = "separately interlocked")
031    private PrintStream logStream;
032
033    public CbusConsoleLoggingPane(CbusConsolePane mainPane){
034        super();
035        _mainPane = mainPane;
036        // set file chooser to a default
037        logFileChooser = new jmri.util.swing.JmriJFileChooser(FileUtil.getUserFilesPath());
038        logFileChooser.setSelectedFile(new File(FileUtil.getUserFilesPath()+"monitorLog.txt"));
039
040        startStopLogButton = new JToggleButton();
041        openLogFileButton = new JButton();
042        openFileChooserButton = new JButton();
043        entryField = new JTextField();
044        logenterButton = new JButton();
045        setupPane();
046
047    }
048
049    private void setupPane() {
050
051        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
052        setBorder(BorderFactory.createTitledBorder(
053            BorderFactory.createEtchedBorder(), Bundle.getMessage("Logging")));
054
055        setButtonToolTips();
056
057        add(startStopLogButton);
058        add(openFileChooserButton);
059        add(openLogFileButton);
060        add(logenterButton);
061        add(entryField);
062
063        addListeners();
064
065    }
066
067    private void setSelectFileToolTip() {
068
069        openFileChooserButton.setToolTipText(logFileChooser.getSelectedFile().getPath());
070
071
072    }
073
074    private void addListeners() {
075
076        startStopLogButton.addActionListener((java.awt.event.ActionEvent e) -> {
077
078            openFileChooserButton.setEnabled(!startStopLogButton.isSelected());
079
080            if (startStopLogButton.isSelected()){
081                startLogButtonActionPerformed(e);
082            }
083            else {
084                stopLogButtonActionPerformed(e);
085            }
086
087            updateStartStopButtonText();
088
089        });
090
091        openFileChooserButton.addActionListener(this::openFileChooserButtonActionPerformed);
092
093        openLogFileButton.addActionListener((java.awt.event.ActionEvent e) -> {
094            try {
095                openLogFileActionPerformed(e);
096            } catch (IOException ex) {
097                log.error("log file open exception", ex);
098            }
099        });
100
101        logenterButton.addActionListener(this::textToLogButtonActionPerformed);
102        entryField.addActionListener(this::textToLogButtonActionPerformed);
103
104        updateStartStopButtonText();
105
106    }
107
108    private void setButtonToolTips() {
109
110        logenterButton.setText(Bundle.getMessage("ButtonAddMessage"));
111        logenterButton.setToolTipText(Bundle.getMessage("TooltipAddMessage"));
112
113        openFileChooserButton.setText(Bundle.getMessage("ButtonChooseLogFile"));
114        setSelectFileToolTip();
115
116        openLogFileButton.setText(Bundle.getMessage("OpenLogFile"));
117        openLogFileButton.setToolTipText(Bundle.getMessage("OpenLogFileTip"));
118
119        entryField.setToolTipText(Bundle.getMessage("EntryAddtoLogTip"));
120
121    }
122
123    private void updateStartStopButtonText(){
124
125        if (startStopLogButton.isSelected()){
126
127            startStopLogButton.setText(Bundle.getMessage("ButtonStopLogging"));
128            startStopLogButton.setToolTipText(Bundle.getMessage("TooltipStopLogging"));
129            startStopLogButton.setForeground(Color.red);
130
131        }
132        else {
133
134            startStopLogButton.setText(Bundle.getMessage("ButtonStartLogging"));
135            startStopLogButton.setToolTipText(Bundle.getMessage("TooltipStartLogging") + " " +
136                Bundle.getMessage("ButtonStartLogTipExtra"));
137            startStopLogButton.setForeground(new JToggleButton().getForeground());
138
139        }
140
141    }
142
143    private void startLogButtonActionPerformed(java.awt.event.ActionEvent e) {
144        // start logging by creating the stream
145        if (logStream == null) {  // successive clicks don't restart the file
146            // start logging
147            try {
148                logStream = new PrintStream(new FileOutputStream(logFileChooser.getSelectedFile()));
149            } catch (FileNotFoundException ex) {
150                log.error("exception", ex);
151            }
152        }
153    }
154
155    private void stopLogButtonActionPerformed(java.awt.event.ActionEvent e) {
156        // stop logging by removing the stream
157        if (logStream != null) {
158            logStream.flush();
159            logStream.close();
160        }
161        logStream = null;
162    }
163
164    private void openFileChooserButtonActionPerformed(java.awt.event.ActionEvent e) {
165        // start at current file, show dialog
166        int retVal = logFileChooser.showSaveDialog(this);
167
168        // handle selection or cancel
169        if (retVal == JFileChooser.APPROVE_OPTION) {
170            boolean loggingNow = (logStream != null);
171            stopLogButtonActionPerformed(e);  // stop before changing file
172            //File file = logFileChooser.getSelectedFile();
173            // if we were currently logging, start the new file
174            if (loggingNow) {
175                startLogButtonActionPerformed(e);
176            }
177        }
178        setSelectFileToolTip();
179    }
180
181    private void openLogFileActionPerformed(java.awt.event.ActionEvent e) throws IOException {
182        // start at current file, show dialog
183        Desktop desktop = Desktop.getDesktop();
184        File dirToOpen;
185
186        try {
187            dirToOpen = logFileChooser.getSelectedFile();
188            desktop.open(dirToOpen);
189        } catch (IllegalArgumentException iae) {
190            JmriJOptionPane.showMessageDialog(_mainPane,
191                (Bundle.getMessage("NoOpenLogFile")), Bundle.getMessage("WarningTitle"),
192                JmriJOptionPane.ERROR_MESSAGE);
193        }
194
195    }
196
197    private void textToLogButtonActionPerformed(java.awt.event.ActionEvent e) {
198        _mainPane.nextLine(entryField.getText() + "\n", entryField.getText() + "\n", -1);
199    }
200
201    private final String newline = System.getProperty("line.separator");
202
203    protected void sendLogToFile( String sbCbus ){
204        if (logStream != null) {
205            String logLine = sbCbus;
206            if (!newline.equals("\n")) {
207                // have to massage the line-ends
208                StringBuilder out = new StringBuilder(sbCbus.length() + 10);  // arbitrary guess at space
209                for (int j = 0; j < sbCbus.length(); j++) {
210                    if (sbCbus.charAt(j) == '\n') {
211                        out.append(newline);
212                    } else {
213                        out.append(sbCbus.charAt(j));
214                    }
215                }
216                logLine = new String(out);
217            }
218            logStream.print(logLine);
219        }
220    }
221
222    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusConsoleLoggingPane.class);
223
224}