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