Author: [log in to unmask] Date: Mon Mar 9 15:46:12 2015 New Revision: 2383 Log: Add logging to terminal or file via a menu item. HPSJAVA-462 Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java Mon Mar 9 15:46:12 2015 @@ -38,10 +38,15 @@ static final String SAVE_PLOTS = "savePlots"; static final String CLEAR_PLOTS = "resetPlots"; + // Exit the application. static final String EXIT = "exit"; + + // Log to file or standard print stream. + static final String LOG_TO_FILE = "logToFile"; + static final String LOG_TO_TERMINAL = "logToTerminal"; - static final String LOG_LEVEL_FILTER_CHANGED = "logLevelFilterChanged"; - + static final String LOG_LEVEL_FILTER_CHANGED = "logLevelFilterChanged"; + //////////////////////////////////////////// static final String BLOCKING_CHANGED = "blockingChanged"; static final String CHOOSE_COMPACT_FILE = "chooseCompactFile"; @@ -59,10 +64,7 @@ static final String FREEZE_CONDITIONS_CHANGED = "freezeConditionsChanged"; static final String LOG_LEVEL_CHANGED = "logLevelChanged"; - static final String LOG_TO_FILE = "logToFile"; - static final String LOG_TO_FILE_CHANGED = "logToFileChanged"; - static final String LOG_TO_TERMINAL = "logToTerminal"; - + static final String PROCESSING_STAGE_CHANGED = "processingStageChanged"; static final String SAVE_LOG_TABLE = "saveLogTable"; static final String SELECT_LOG_FILE = "logToFile"; Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java Mon Mar 9 15:46:12 2015 @@ -1,7 +1,29 @@ package org.hps.monitoring.application; -import static org.hps.monitoring.application.Commands.*; -import static org.hps.monitoring.application.model.ConfigurationModel.*; +import static org.hps.monitoring.application.Commands.DETECTOR_ALIAS_CHANGED; +import static org.hps.monitoring.application.Commands.DETECTOR_NAME_CHANGED; +import static org.hps.monitoring.application.Commands.DISCONNECT_ON_END_RUN_CHANGED; +import static org.hps.monitoring.application.Commands.DISCONNECT_ON_ERROR_CHANGED; +import static org.hps.monitoring.application.Commands.EVENT_BUILDER_CHANGED; +import static org.hps.monitoring.application.Commands.FREEZE_CONDITIONS_CHANGED; +import static org.hps.monitoring.application.Commands.LOG_LEVEL_CHANGED; +import static org.hps.monitoring.application.Commands.STEERING_RESOURCE_CHANGED; +import static org.hps.monitoring.application.Commands.STEERING_TYPE_CHANGED; +import static org.hps.monitoring.application.Commands.USER_RUN_NUMBER_CHANGED; +import static org.hps.monitoring.application.model.ConfigurationModel.DETECTOR_ALIAS_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.DETECTOR_NAME_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.DISCONNECT_ON_END_RUN_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.DISCONNECT_ON_ERROR_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.EVENT_BUILDER_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.FREEZE_CONDITIONS_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.LOG_FILE_NAME_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.LOG_LEVEL_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.LOG_TO_FILE_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.MAX_EVENTS_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.STEERING_FILE_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.STEERING_RESOURCE_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.STEERING_TYPE_PROPERTY; +import static org.hps.monitoring.application.model.ConfigurationModel.USER_RUN_NUMBER_PROPERTY; import java.awt.GridBagLayout; import java.awt.Insets; @@ -18,6 +40,7 @@ import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JTextField; +import javax.swing.border.EmptyBorder; import javax.swing.filechooser.FileFilter; import org.hps.monitoring.application.model.ConfigurationModel; @@ -44,10 +67,10 @@ private JCheckBox freezeConditionsCheckBox; private JTextField maxEventsField; private JCheckBox disconnectOnErrorCheckBox; - private JCheckBox disconnectOnEndRunCheckBox; - private JTextField logFileNameField; + private JCheckBox disconnectOnEndRunCheckBox; private JComboBox<?> logLevelComboBox; private JCheckBox logToFileCheckbox; + private JTextField logFileNameField; // The package where steering resources must be located. static final String STEERING_PACKAGE = "org/hps/steering/monitoring/"; @@ -68,9 +91,13 @@ /** * Class constructor. */ - JobSettingsPanel() { - - super(new Insets(4, 2, 2, 4), true); + JobSettingsPanel(ConfigurationModel model) { + + super(new Insets(5, 3, 3, 5), true); + + setBorder(new EmptyBorder(10, 10, 10, 10)); + + model.addPropertyChangeListener(this); setLayout(new GridBagLayout()); @@ -136,11 +163,9 @@ logToFileCheckbox = addCheckBox("Log to File", false, false); logToFileCheckbox.setEnabled(false); - logToFileCheckbox.setActionCommand(LOG_TO_FILE_CHANGED); - logToFileCheckbox.addActionListener(this); - - logFileNameField = addField("Log File", "", "Full path to log file.", 30, false); - logFileNameField.addPropertyChangeListener("value", this); + + logFileNameField = addField("Log File Name", "", "Full path to log file.", 50, false); + logFileNameField.setEditable(false); } @Override @@ -152,8 +177,6 @@ * Attaches the ActionListener from the main app to specific GUI components in this class. */ public void addActionListener(ActionListener listener) { - logFileNameField.addActionListener(listener); - logToFileCheckbox.addActionListener(listener); steeringResourcesComboBox.addActionListener(listener); freezeConditionsCheckBox.addActionListener(listener); } @@ -252,8 +275,6 @@ configurationModel.setSteeringType(SteeringType.valueOf((String) steeringTypeComboBox.getSelectedItem())); } else if (STEERING_RESOURCE_CHANGED.equals(event.getActionCommand())) { configurationModel.setSteeringResource((String) steeringResourcesComboBox.getSelectedItem()); - } else if (LOG_TO_FILE_CHANGED.equals(event.getActionCommand())) { - configurationModel.setLogToFile(logToFileCheckbox.isSelected()); } else if (LOG_LEVEL_CHANGED.equals(event.getActionCommand())) { configurationModel.setLogLevel(Level.parse((String) logLevelComboBox.getSelectedItem())); } else if (EVENT_BUILDER_CHANGED.equals(event.getActionCommand())) { @@ -279,8 +300,8 @@ } /** - * Updates the configuration with changes from the GUI component values. The changes from the - * GUI are distinguishable by their component object. + * Updates the configuration with changes from the GUI component values. + * The changes from the GUI are distinguishable by their component object. */ @Override public void propertyChange(PropertyChangeEvent evt) { @@ -289,8 +310,6 @@ Object source = evt.getSource(); if (source == steeringFileField) { configurationModel.setSteeringFile(steeringFileField.getText()); - } else if (source == logFileNameField) { - configurationModel.setLogFileName(logFileNameField.getText()); } else if (source == userRunNumberField) { // Is run number being reset to null or empty? if (userRunNumberField.getText() == null || userRunNumberField.getText().isEmpty()) { @@ -314,7 +333,21 @@ } } else if (source == maxEventsField) { configurationModel.setMaxEvents(Long.parseLong(maxEventsField.getText())); - System.out.println("setMaxEvents - " + configurationModel.getMaxEvents()); + //System.out.println("setMaxEvents - " + configurationModel.getMaxEvents()); + } else if (evt.getPropertyName().equals(ConfigurationModel.LOG_TO_FILE_PROPERTY)) { + // This is getting the log to file prop change from the ConfigurationModel to update a read only component. + Boolean logToFile = (Boolean) evt.getNewValue(); + if (logToFile != null) { + logToFileCheckbox.setSelected(logToFile); + } + } else if (evt.getPropertyName().equals(ConfigurationModel.LOG_FILE_NAME_PROPERTY)) { + // This is getting the log file name prop change from the ConfigurationModel to update a read only component. + String logFileName = (String) evt.getNewValue(); + if (logFileName != null && logFileName.length() > 0) { + logFileNameField.setText(logFileName); + } else { + logFileNameField.setText(""); + } } } finally { configurationModel.addPropertyChangeListener(this); Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java Mon Mar 9 15:46:12 2015 @@ -16,7 +16,7 @@ * * @author Jeremy McCormick <[log in to unmask]> */ -public class LogLevelFilterComboBox extends JComboBox<Level> implements ActionListener, PropertyChangeListener { +class LogLevelFilterComboBox extends JComboBox<Level> implements ActionListener, PropertyChangeListener { ConfigurationModel configurationModel; Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java Mon Mar 9 15:46:12 2015 @@ -17,11 +17,16 @@ * This is a simple GUI component for the log table and its controls. * @author Jeremy McCormick <[log in to unmask]> */ -public class LogPanel extends JPanel { +class LogPanel extends JPanel{ LogTable logTable; + LogLevelFilterComboBox logFilterComboBox; + + ConfigurationModel configurationModel; LogPanel(ConfigurationModel configurationModel, ActionListener listener) { + + this.configurationModel = configurationModel; setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); @@ -31,8 +36,8 @@ controlsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 5)); JLabel label = new JLabel("Log Level Filter"); - LogLevelFilterComboBox logFilterComboBox = new LogLevelFilterComboBox(configurationModel); - logFilterComboBox.setToolTipText("Messages below this level will be filtered out."); + logFilterComboBox = new LogLevelFilterComboBox(configurationModel); + logFilterComboBox.setToolTipText("Messages below this level will be filtered out."); controlsPanel.add(label); controlsPanel.add(logFilterComboBox); @@ -51,5 +56,5 @@ add(controlsPanel, BorderLayout.PAGE_START); add(tablePane, BorderLayout.PAGE_END); - } + } } Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java Mon Mar 9 15:46:12 2015 @@ -132,5 +132,5 @@ filterLevel = (Level) event.getNewValue(); model.fireTableDataChanged(); } - } + } } Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java Mon Mar 9 15:46:12 2015 @@ -10,7 +10,6 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.hps.monitoring.application.model.Configuration; - /** * This is the front-end for running the monitoring app via a {@link #main(String[])} method. Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java Mon Mar 9 15:46:12 2015 @@ -39,16 +39,17 @@ JMenuItem closeFileItem; JMenuItem openFileItem; JMenu settingsMenu; - ConfigurationModel configurationModel; + JMenuItem logItem; + ConfigurationModel configurationModel; MenuBar(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel, ActionListener listener) { - - // Do not need to listen for changes on this model. - this.configurationModel = configurationModel; + + this.configurationModel = configurationModel; + this.configurationModel.addPropertyChangeListener(this); // Need to listen for connection status changes. - connectionModel.addPropertyChangeListener(this); - + connectionModel.addPropertyChangeListener(this); + JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic(KeyEvent.VK_F); add(fileMenu); @@ -138,6 +139,14 @@ screenshotItem.setToolTipText("Save a screenshot to a graphics file"); toolsMenu.add(screenshotItem); + logItem = new JMenuItem("Log to File ..."); + logItem.setMnemonic(KeyEvent.VK_R); + logItem.setActionCommand(Commands.LOG_TO_FILE); + logItem.addActionListener(listener); + logItem.setEnabled(true); + logItem.setToolTipText("Redirect System.out to a file instead of terminal"); + toolsMenu.add(logItem); + JMenu windowMenu = new JMenu("Window"); windowMenu.setMnemonic(KeyEvent.VK_W); add(windowMenu); @@ -164,64 +173,34 @@ defaultsItem.addActionListener(listener); defaultsItem.setEnabled(true); defaultsItem.setToolTipText("Restore the window defaults"); - windowMenu.add(defaultsItem); - - /* - - JMenu logMenu = new JMenu("Log"); - logMenu.setMnemonic(KeyEvent.VK_L); - add(logMenu); - - logItem = new JMenuItem("Redirect to File ..."); - logItem.setMnemonic(KeyEvent.VK_F); - logItem.setActionCommand(CHOOSE_LOG_FILE); - //logItem.addActionListener(this); - logItem.setEnabled(true); - logItem.setToolTipText("Redirect std out and err to a file."); - logMenu.add(logItem); - - terminalItem = new JMenuItem("Redirect to Terminal"); - terminalItem.setMnemonic(KeyEvent.VK_T); - terminalItem.setActionCommand(LOG_TO_TERMINAL); - //terminalItem.addActionListener(this); - terminalItem.setEnabled(false); - terminalItem.setToolTipText("Redirect std out and err back to the terminal."); - logMenu.add(terminalItem); - - JMenuItem saveLogItem = new JMenuItem("Save Log Table to File ..."); - saveLogItem.setMnemonic(KeyEvent.VK_S); - saveLogItem.setActionCommand(SAVE_LOG_TABLE); - //saveLogItem.addActionListener(this); - saveLogItem.setToolTipText("Save the log records to a tab delimited text file."); - logMenu.add(saveLogItem); - - JMenuItem clearLogItem = new JMenuItem("Clear Log Table"); - //clearLogItem.addActionListener(this); - clearLogItem.setMnemonic(KeyEvent.VK_C); - clearLogItem.setActionCommand(CLEAR_LOG_TABLE); - clearLogItem.setToolTipText("Clear the log table of all messages."); - logMenu.add(clearLogItem); - - JMenu utilMenu = new JMenu("Util"); - plotsMenu.setMnemonic(KeyEvent.VK_U); - add(utilMenu); - - JMenuItem screenshotItem = new JMenuItem("Take a Screenshot ..."); - screenshotItem.setMnemonic(KeyEvent.VK_N); - screenshotItem.setActionCommand(SCREENSHOT); - //screenshotItem.addActionListener(this); - screenshotItem.setToolTipText("Save a screenshot to file"); - utilMenu.add(screenshotItem); - */ + windowMenu.add(defaultsItem); } @Override public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) { - ConnectionStatus status = (ConnectionStatus) evt.getNewValue(); - boolean connected = status.equals(ConnectionStatus.CONNECTED); - closeFileItem.setEnabled(!connected); - openFileItem.setEnabled(!connected); + configurationModel.removePropertyChangeListener(this); + try { + if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) { + ConnectionStatus status = (ConnectionStatus) evt.getNewValue(); + boolean connected = status.equals(ConnectionStatus.CONNECTED); + closeFileItem.setEnabled(!connected); + openFileItem.setEnabled(!connected); + } else if (evt.getPropertyName().equals(ConfigurationModel.LOG_TO_FILE_PROPERTY)) { + Boolean logToFile = (Boolean) evt.getNewValue(); + if (logToFile == true) { + // Toggle log item state to send to terminal. + logItem.setText("Log to Terminal ..."); + logItem.setActionCommand(Commands.LOG_TO_TERMINAL); + logItem.setToolTipText("Log messages to the terminal"); + } else { + // Toggle log item state to send to file. + logItem.setText("Log to File ..."); + logItem.setActionCommand(Commands.LOG_TO_FILE); + logItem.setToolTipText("Log messages to a file"); + } + } + } finally { + configurationModel.addPropertyChangeListener(this); } } @@ -234,6 +213,5 @@ closeFileItem.setEnabled(false); } } - } - + } } Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java Mon Mar 9 15:46:12 2015 @@ -14,7 +14,10 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; @@ -32,7 +35,6 @@ import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; -import org.hps.conditions.database.DatabaseConditionsManager; import org.hps.monitoring.application.DataSourceComboBox.DataSourceItem; import org.hps.monitoring.application.LogTable.LogRecordModel; import org.hps.monitoring.application.model.Configuration; @@ -73,7 +75,9 @@ static final Level DEFAULT_LEVEL = Level.ALL; // Default log stream. - PrintStream logStream = System.out; + MonitoringApplicationStreamHandler streamHandler; + PrintStream sysOut = System.out; + PrintStream sysErr = System.err; // Application error handling. final ErrorHandler errorHandler; @@ -124,6 +128,22 @@ LogTable getLogTable() { return frame.logPanel.logTable; + } + + class MonitoringApplicationStreamHandler extends StreamHandler { + + MonitoringApplicationStreamHandler(PrintStream ps) { + super(ps, new DefaultLogFormatter()); + } + + public void publish(LogRecord record) { + super.publish(record); + flush(); + } + + public void setOutputStream(OutputStream out) { + super.setOutputStream(out); + } } /** @@ -160,6 +180,21 @@ loadConfiguration(this.configuration); logger.info("application initialized successfully"); + } + + /** + * Setup the logger. + */ + void setupLogger() { + logger.setUseParentHandlers(false); + logger.addHandler(new LogHandler()); + streamHandler = new MonitoringApplicationStreamHandler(System.out); + logger.addHandler(streamHandler); + for (Handler handler : logger.getHandlers()) { + handler.setLevel(DEFAULT_LEVEL); + } + logger.setLevel(DEFAULT_LEVEL); + logger.info("logging initialized"); } /** @@ -229,7 +264,11 @@ saveLogTable(); } else if (Commands.CLEAR_LOG_TABLE.equals(cmd)) { getLogRecordModel().clear(); - } + } else if (Commands.LOG_TO_FILE.equals(cmd)) { + chooseLogFile(); + } else if (Commands.LOG_TO_TERMINAL.equals(cmd)) { + logToTerminal(); + } } /** @@ -255,26 +294,7 @@ // Perform global configuration of the JFreeChart back end. AnalysisFactory.configure(); } - - /** - * Setup the logger. - */ - void setupLogger() { - logger.setUseParentHandlers(false); - logger.addHandler(new LogHandler()); - logger.addHandler(new StreamHandler(logStream, new DefaultLogFormatter()) { - public void publish(LogRecord record) { - super.publish(record); - flush(); - } - }); - for (Handler handler : logger.getHandlers()) { - handler.setLevel(DEFAULT_LEVEL); - } - logger.setLevel(DEFAULT_LEVEL); - logger.info("logging initialized"); - } - + /** * This method sets the configuration on the model, which fires a change for every property. * @param configuration The new configuration. @@ -644,4 +664,87 @@ void saveLogTable() { saveTable(frame.logPanel.logTable); } + + /** + * Redirect <code>System.out</code> and <code>System.err</code> to file chosen + * by a file chooser. + */ + void chooseLogFile() { + JFileChooser fc = new JFileChooser(); + fc.setAcceptAllFileFilterUsed(false); + fc.setDialogTitle("Save Log Messages to File"); + fc.setCurrentDirectory(new File(".")); + int r = fc.showSaveDialog(frame); + if (r == JFileChooser.APPROVE_OPTION) { + String fileName = fc.getSelectedFile().getPath(); + if (new File(fileName).exists()) { + DialogUtil.showErrorDialog(frame, "File Exists", "File already exists."); + } else { + logToFile(new File(fileName)); + } + } + } + + /** + * Redirect <code>System.out</code> and <code>System.err</code> to a file. + * @param file The output log file. + * @throws FileNotFoundException if the file does not exist. + */ + void logToFile(File file) { + try { + + // Create the output file stream. + PrintStream fileStream = new PrintStream(new FileOutputStream(file.getPath())); + System.setOut(fileStream); + System.setErr(fileStream); + + // Flush the current handler, but do NOT close here or System.out gets clobbered! + streamHandler.flush(); + + // Replace the current handler with one using the file stream. + logger.removeHandler(streamHandler); + streamHandler = new MonitoringApplicationStreamHandler(fileStream); + streamHandler.setLevel(logger.getLevel()); + logger.addHandler(streamHandler); + + // Set the properties on the model. + configurationModel.setLogFileName(file.getPath()); + configurationModel.setLogToFile(true); + + logger.info("Saving log messages to " + configurationModel.getLogFileName()); + DialogUtil.showInfoDialog(frame, "Logging to File", + "Log messages redirected to file" + '\n' + configurationModel.getLogFileName()); + + } catch (FileNotFoundException e) { + errorHandler.setError(e).log().showErrorDialog(); + } + } + + /** + * Send <code>System.out</code> and <code>System.err</code> back to the terminal, + * e.g. if they were previously sent to a file. + */ + void logToTerminal() { + + // Reset System.out and err back to original streams. + System.setOut(sysOut); + System.setErr(sysErr); + + // Flush and close the current handler, which is using a file stream. + streamHandler.flush(); + streamHandler.close(); + + // Replace the handler with the one printing to the terminal. + logger.removeHandler(streamHandler); + streamHandler = new MonitoringApplicationStreamHandler(System.out); + streamHandler.setLevel(logger.getLevel()); + logger.addHandler(streamHandler); + + logger.log(Level.INFO, "log messages redirected to terminal"); + + // Update the model to indicate logging to file has been disabled. + configurationModel.setLogToFile(false); + + DialogUtil.showInfoDialog(frame, "Log to Terminal", "Log messages will be sent to the terminal."); + } } Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java Mon Mar 9 15:46:12 2015 @@ -38,9 +38,9 @@ /** * <p> * This is a GUI component for showing the statistics and other information about an AIDA plot - * when it is clicked on in the monitoring app. + * when it is clicked on in the monitoring application. * <p> - * The information is updated dynamically via the <code>AIDAObserver</code> API on the AIDA object. + * The information in the table is updated dynamically via the <code>AIDAObserver</code> API on the AIDA object. */ class PlotInfoPanel extends JPanel implements AIDAListener, ActionListener, FunctionListener { Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java Mon Mar 9 15:46:12 2015 @@ -6,7 +6,7 @@ import javax.swing.JTabbedPane; /** - * This is the panel containing the monitoring plots. + * This is the panel containing the tabs with the monitoring plots. * @author Jeremy McCormick <[log in to unmask]> */ class PlotPanel extends JPanel { Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java Mon Mar 9 15:46:12 2015 @@ -31,7 +31,7 @@ this.parent = parent; connectionPanel = new ConnectionSettingsPanel(); - jobPanel = new JobSettingsPanel(); + jobPanel = new JobSettingsPanel(configurationModel); // Push configuration to sub-components. connectionPanel.setConfigurationModel(configurationModel); @@ -55,7 +55,6 @@ add(Box.createRigidArea(new Dimension(1, 5))); JPanel buttonsPanel = new JPanel(); buttonsPanel.add(okayButton); - //buttonsPanel.add(defaultsButton); buttonsPanel.setLayout(new FlowLayout()); add(buttonsPanel); add(Box.createRigidArea(new Dimension(1, 5))); Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java ============================================================================= --- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java (original) +++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java Mon Mar 9 15:46:12 2015 @@ -21,7 +21,7 @@ * * @author Jeremy McCormick <[log in to unmask]> */ -public class TriggerDiagnosticsPanel extends JPanel { +class TriggerDiagnosticsPanel extends JPanel { JTabbedPane tabs = new JTabbedPane(); ClusterTablePanel clusterPanel = new ClusterTablePanel();