Author: [log in to unmask] Date: Sat Mar 14 12:37:17 2015 New Revision: 2453 Log: Updates and fixes to monitoring app on dev branch. Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventDashboard.java - copied, changed from r2434, java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/RunPanel.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java Removed: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/RunPanel.java Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/Commands.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotPanel.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusTable.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/RunnableEtStation.java Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/Commands.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/Commands.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/Commands.java Sat Mar 14 12:37:17 2015 @@ -34,9 +34,10 @@ // Save a screenshot static final String SAVE_SCREENSHOT = "saveScreenshot"; - // Save the plots + // Plotting actions static final String SAVE_PLOTS = "savePlots"; static final String CLEAR_PLOTS = "resetPlots"; + static final String SAVE_SELECTED_PLOTS = "saveSelectedPlots"; // Exit the application. static final String EXIT = "exit"; Copied: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventDashboard.java (from r2434, java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/RunPanel.java) ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/RunPanel.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventDashboard.java Sat Mar 14 12:37:17 2015 @@ -23,7 +23,7 @@ * Dashboard for displaying information about the current run. * @author Jeremy McCormick <[log in to unmask]> */ -class RunPanel extends JPanel implements PropertyChangeListener { +class EventDashboard extends JPanel implements PropertyChangeListener { FieldPanel runNumberField = new FieldPanel("Run Number", "", 10, false); DatePanel startDateField = new DatePanel("Run Start", "", 16, false); @@ -35,17 +35,17 @@ FieldPanel dataReceivedField = new FieldPanel("Data Received [MB]", "", 14, false); FieldPanel eventNumberField = new FieldPanel("Event Number", "", 14, false); FieldPanel dataRateField = new FieldPanel("Data Rate [MB/s]", "", 12, false); - FieldPanel eventRateField = new FieldPanel("Event Rate [evt/s]", "", 14, false); + FieldPanel eventRateField = new FieldPanel("Event Rate [Hz]", "", 14, false); RunModel runModel; static final NumberFormat formatter = new DecimalFormat("#0.00"); - public RunPanel() { + public EventDashboard() { build(); } - public RunPanel(RunModel runModel) { + public EventDashboard(RunModel runModel) { this.runModel = runModel; this.runModel.addPropertyChangeListener(this); build(); @@ -73,7 +73,7 @@ this.runModel = runModel; } - class RunPanelUpdater extends CompositeRecordProcessor { + class EventDashboardUpdater extends CompositeRecordProcessor { Timer timer; Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java Sat Mar 14 12:37:17 2015 @@ -94,6 +94,18 @@ * @param configurationModel The global configuration. */ void setup(ConfigurationModel configurationModel) { + + // Setup LCSim from the configuration. + setupLcsim(configurationModel); + + // Now setup the CompositeLoop. + setupLoop(configurationModel); + } + + /** + * @param configurationModel + */ + private void setupLcsim(ConfigurationModel configurationModel) { MonitoringApplication.logger.info("setting up LCSim"); // Get steering resource or file as a String parameter. @@ -168,15 +180,12 @@ // Catch all errors and rethrow them as RuntimeExceptions. application.errorHandler.setError(t).setMessage("Error setting up LCSim.").printStackTrace().raiseException(); } - - // Now setup the CompositeLoop. - setupLoop(configurationModel); } /** * Create the event builder for converting EVIO events to LCSim. */ - void createEventBuilder(ConfigurationModel configurationModel) { + private void createEventBuilder(ConfigurationModel configurationModel) { // Get the class for the event builder. String eventBuilderClassName = configurationModel.getEventBuilderClassName(); @@ -196,7 +205,7 @@ * Setup the loop from the global configuration. * @param configurationModel The global configuration. */ - void setupLoop(ConfigurationModel configurationModel) { + private void setupLoop(ConfigurationModel configurationModel) { CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration().setStopOnEndRun(configurationModel.getDisconnectOnEndRun()).setStopOnErrors(configurationModel.getDisconnectOnError()).setDataSourceType(configurationModel.getDataSourceType()).setProcessingStage(configurationModel.getProcessingStage()).setEtConnection(sessionState.connection).setFilePath(configurationModel.getDataSourcePath()).setLCSimEventBuilder(sessionState.eventBuilder); @@ -238,9 +247,11 @@ logger.config("added extra Driver " + driver.getName() + " to job"); } - // Enable conditions system activation from EVIO event information. - logger.config("added EvioDetectorConditionsProcessor to job with detector " + configurationModel.getDetectorName()); - loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName())); + // Enable conditions system activation from EVIO event data if using an EVIO file source. + if (configurationModel.getDataSourceType().equals(DataSourceType.EVIO_FILE)) { + logger.config("added EvioDetectorConditionsProcessor to job with detector " + configurationModel.getDetectorName()); + loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName())); + } // Create the CompositeLoop with the configuration. sessionState.loop = new CompositeLoop(loopConfig); @@ -250,7 +261,7 @@ * Setup a steering file on disk. * @param steering The steering file. */ - void setupSteeringFile(String steering) { + private void setupSteeringFile(String steering) { sessionState.jobManager.setup(new File(steering)); } @@ -259,7 +270,7 @@ * @param steering The steering resource. * @throws IOException if there is a problem setting up or accessing the resource. */ - void setupSteeringResource(String steering) throws IOException { + private void setupSteeringResource(String steering) throws IOException { InputStream is = this.getClass().getClassLoader().getResourceAsStream(steering); if (is == null) throw new IOException("Steering resource is not accessible or does not exist."); @@ -437,7 +448,7 @@ // Add an attachment that listens for DAQ configuration changes via physics SYNC events. createPhysicsSyncStation(); - // Add ann attachment that listens for PRESTART events. + // Add an attachment that listens for PRESTART events. createPreStartStation(); } catch (Exception e) { @@ -478,7 +489,7 @@ /** * Create the ET that listens for DAQ configuration change via SYNC events. */ - void createPhysicsSyncStation() { + private void createPhysicsSyncStation() { logger.fine("creating physics SYNC station ..."); PhysicsSyncEventStation configStation = new PhysicsSyncEventStation( this.sessionState.connection.getEtSystem(), @@ -492,7 +503,7 @@ /** * Create the ET station that listens for GO events in order to initialize the conditions system. */ - void createPreStartStation() { + private void createPreStartStation() { logger.fine("creating PRESTART station ..."); String detectorName = this.application.configurationModel.getDetectorName(); EtSystem system = this.sessionState.connection.getEtSystem(); Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java Sat Mar 14 12:37:17 2015 @@ -5,10 +5,6 @@ import hep.aida.jfree.plotter.PlotterRegionListener; import hep.aida.ref.remote.rmi.client.RmiStoreFactory; -import java.awt.Dimension; -import java.awt.Rectangle; -import java.awt.Robot; -import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; @@ -50,7 +46,6 @@ import org.hps.monitoring.application.util.TableExporter; import org.hps.monitoring.plotting.MonitoringAnalysisFactory; import org.hps.monitoring.plotting.MonitoringPlotFactory; -import org.hps.monitoring.subsys.StatusCode; import org.hps.monitoring.subsys.SystemStatus; import org.hps.monitoring.subsys.SystemStatusListener; import org.hps.monitoring.subsys.SystemStatusRegistry; @@ -69,7 +64,7 @@ * * @author Jeremy McCormick <[log in to unmask]> */ -final class MonitoringApplication implements ActionListener, PropertyChangeListener, SystemStatusListener { +final class MonitoringApplication implements ActionListener, PropertyChangeListener { // Statically initialize logging, which will be fully setup later. static final Logger logger; @@ -344,11 +339,14 @@ * Reset the plots and clear the tabs in the plot window. */ void resetPlots() { - + + // Clear global list of registered plotters. + MonitoringPlotFactory.getPlotterRegistry().clear(); + // Clear the static AIDA tree in case plots are hanging around from previous sessions. AIDA.defaultInstance().clearAll(); - // Reset plot panel which removes all tabs. + // Reset plot panel which removes all its tabs. frame.plotPanel.reset(); logger.info("plots were cleared"); @@ -358,43 +356,20 @@ * Configure the system status monitor panel for a new job. */ void setupSystemStatusMonitor() { + // Clear the system status monitor table. - frame.systemStatusTable.getTableModel().clear(); + frame.systemStatusPanel.clear(); // Get the global registry of SystemStatus objects. SystemStatusRegistry registry = SystemStatusRegistry.getSystemStatusRegistery(); // Process the SystemStatus objects. for (SystemStatus systemStatus : registry.getSystemStatuses()) { - // Add a row to the table for every SystemStatus. - frame.systemStatusTable.getTableModel().addSystemStatus(systemStatus); - - // Add this class as a listener so all status changes can be logged. - systemStatus.addListener(this); + // This will add the status to the two tables. + frame.systemStatusPanel.addSystemStatus(systemStatus); } logger.info("system status monitor initialized successfully"); - } - - /** - * Hook for logging all status changes from the system status monitor. - */ - @Override - public void statusChanged(SystemStatus status) { - - // Choose the appropriate log level. - Level level = Level.FINE; - if (status.getStatusCode().equals(Level.WARNING)) { - level = Level.WARNING; - } else if (status.getStatusCode().ordinal() >= StatusCode.ERROR.ordinal()) { - level = Level.SEVERE; - } - - // Log all status changes. - logger.log(level, "STATUS, " + "subsys: " + status.getSubsystem() + ", " - + "code: " + status.getStatusCode().name() - + ", " + "descr: " + status.getDescription() - + ", " + "mesg: " + status.getMessage()); } /** @@ -416,7 +391,7 @@ // List of extra composite record processors including the updater for the RunPanel. List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>(); - processors.add(frame.runPanel.new RunPanelUpdater()); + processors.add(frame.dashboardPanel.new EventDashboardUpdater()); // Add Driver to update the trigger diagnostics tables. List<Driver> drivers = new ArrayList<Driver>(); @@ -623,6 +598,7 @@ /** * Save a screenshot to a file using a file chooser. */ + // FIXME: This might need to be on a new thread to allow the GUI to redraw w/o chooser visible. void saveScreenshot() { JFileChooser fc = new JFileChooser(); fc.setAcceptAllFileFilterUsed(false); @@ -637,8 +613,17 @@ if (!fileName.endsWith("." + format)) { fileName += "." + format; } + frame.repaint(); + Object lock = new Object(); + synchronized (lock) { + try { + lock.wait(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } writeScreenshot(fileName, format); - DialogUtil.showInfoDialog(frame, "Screenshot Saved", "Screenshot was saved to file."); + DialogUtil.showInfoDialog(frame, "Screenshot Saved", "Screenshot was saved to file" + '\n' + fileName); logger.info("saved screenshot to " + fileName); } } @@ -648,15 +633,13 @@ * @param fileName The name of the output file. */ void writeScreenshot(String fileName, String format) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - Rectangle screenRectangle = new Rectangle(screenSize); + BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_RGB); + frame.paint(image.getGraphics()); try { - Robot robot = new Robot(); - BufferedImage image = robot.createScreenCapture(screenRectangle); ImageIO.write(image, format, new File(fileName)); - } catch (Exception e) { - errorHandler.setError(e).setMessage("Failed to take screenshot.").printStackTrace().log().showErrorDialog(); - } + } catch (IOException e) { + errorHandler.setError(e).setMessage("Failed to save screenshot.").printStackTrace().log().showErrorDialog(); + } } /** Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java Sat Mar 14 12:37:17 2015 @@ -8,7 +8,6 @@ import javax.swing.JFrame; import javax.swing.JPanel; -import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; @@ -21,14 +20,14 @@ */ class MonitoringApplicationFrame extends JFrame { - RunPanel runPanel; + EventDashboard dashboardPanel; PlotPanel plotPanel; PlotInfoPanel plotInfoPanel; LogPanel logPanel; - SystemStatusTable systemStatusTable; JPanel buttonsPanel; TriggerDiagnosticsPanel triggerPanel; ConditionsPanel conditionsPanel; + SystemStatusPanel systemStatusPanel; MenuBar menu; JSplitPane mainSplitPane; @@ -39,9 +38,9 @@ SettingsDialog settingsDialog; - static Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); - static int pixWidthMax = (int) bounds.getWidth(); - static int pixHeightMax = (int) bounds.getHeight(); + static final Rectangle BOUNDS = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); + static final int PIXEL_WIDTH_MAX = (int) BOUNDS.getWidth(); + static final int PIXEL_HEIGHT_MAX = (int) BOUNDS.getHeight(); /** * @@ -58,7 +57,7 @@ setContentPane(contentPanel); contentPanel.setLayout(new BorderLayout()); contentPanel.setOpaque(true); - contentPanel.setPreferredSize(new Dimension(pixWidthMax, pixHeightMax)); + contentPanel.setPreferredSize(new Dimension(PIXEL_WIDTH_MAX, PIXEL_HEIGHT_MAX)); // Create the top panel. JPanel topPanel = new JPanel(); @@ -96,7 +95,7 @@ leftPanel.setLayout(new BorderLayout()); // Create the run dashboard. - runPanel = new RunPanel(application.runModel); + dashboardPanel = new EventDashboard(application.runModel); // Create the tabbed pane for content in bottom of left panel such as log table and system monitor. JTabbedPane tableTabbedPane = new JTabbedPane(); @@ -106,8 +105,9 @@ tableTabbedPane.addTab("Log Messages", logPanel); // Create the system monitor. - systemStatusTable = new SystemStatusTable(); - tableTabbedPane.addTab("System Status Monitor", new JScrollPane(systemStatusTable)); + //systemStatusTable = new SystemStatusTable(); + systemStatusPanel = new SystemStatusPanel(); + tableTabbedPane.addTab("System Status Monitor", systemStatusPanel); // Add the trigger diagnostics tables. triggerPanel = new TriggerDiagnosticsPanel(); @@ -118,19 +118,20 @@ tableTabbedPane.addTab("Detector Conditions", conditionsPanel); // Vertical split pane in left panel. - leftSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, runPanel, tableTabbedPane); - leftSplitPane.setResizeWeight(1.0); + leftSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, dashboardPanel, tableTabbedPane); + leftSplitPane.setDividerLocation(250); leftPanel.add(leftSplitPane, BorderLayout.CENTER); // Create the right panel. JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BorderLayout()); - + // Create the plot info panel. plotInfoPanel = new PlotInfoPanel(); // Create the plot panel. - plotPanel = new PlotPanel(); + plotPanel = new PlotPanel(); + plotInfoPanel.saveButton.addActionListener(plotPanel); // Create the right panel vertical split pane for displaying plots and their information and statistics. rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, plotPanel, plotInfoPanel); @@ -153,6 +154,9 @@ // Setup the frame now that all components have been added. pack(); setExtendedState(JFrame.MAXIMIZED_BOTH); + + System.out.println("dashboard pref size: " + dashboardPanel.getPreferredSize()); + setVisible(true); } Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java Sat Mar 14 12:37:17 2015 @@ -15,10 +15,10 @@ import hep.aida.ref.function.FunctionDispatcher; import hep.aida.ref.function.FunctionListener; +import java.awt.Color; import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; +import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.EventObject; @@ -27,6 +27,8 @@ import java.util.TimerTask; import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JList; import javax.swing.JPanel; @@ -47,6 +49,8 @@ JComboBox<Object> plotComboBox; JTable infoTable = new JTable(); DefaultTableModel model; + JButton saveButton; + PlotterRegion currentRegion; Object currentObject; static final int INSET_SIZE = 5; @@ -63,11 +67,18 @@ */ @SuppressWarnings("unchecked") PlotInfoPanel() { - - setLayout(new GridBagLayout()); - setBorder(BorderFactory.createEmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - - GridBagConstraints c; + + setLayout(new FlowLayout(FlowLayout.LEFT)); + + JPanel leftPanel = new JPanel(); + leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); + + JPanel buttonPanel = new JPanel(); + saveButton = new JButton("Save Plots ..."); + saveButton.setActionCommand(Commands.SAVE_SELECTED_PLOTS); + buttonPanel.add(saveButton); + //c.anchor = GridBagConstraints.NORTHWEST; + leftPanel.add(buttonPanel); plotComboBox = new JComboBox<Object>(); plotComboBox.setActionCommand(PLOT_SELECTED); @@ -85,26 +96,17 @@ } }); plotComboBox.addActionListener(this); - c = new GridBagConstraints(); - c.gridx = 0; - c.gridy = 0; - c.fill = GridBagConstraints.HORIZONTAL; - c.insets = new Insets(0, 0, INSET_SIZE, 0); - add(plotComboBox, c); - + leftPanel.add(plotComboBox); + String data[][] = new String[0][0]; model = new DefaultTableModel(data, COLUMN_NAMES); infoTable.setModel(model); - - // FIXME: Are these adequate column size settings? Could prob be bigger... infoTable.getColumn("Field").setMinWidth(25); infoTable.getColumn("Value").setMinWidth(20); - - c = new GridBagConstraints(); - c.gridx = 0; - c.gridy = 1; - c.fill = GridBagConstraints.BOTH; - add(infoTable, c); + infoTable.setMinimumSize(new Dimension(100, 200)); + leftPanel.add(infoTable); + + add(leftPanel); } /** Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotPanel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotPanel.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/PlotPanel.java Sat Mar 14 12:37:17 2015 @@ -1,15 +1,26 @@ package org.hps.monitoring.application; +import hep.aida.IPlotter; + import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JTabbedPane; + +import org.hps.monitoring.application.util.DialogUtil; +import org.hps.monitoring.plotting.MonitoringPlotFactory; /** * This is the panel containing the tabs with the monitoring plots. * @author Jeremy McCormick <[log in to unmask]> */ -class PlotPanel extends JPanel { +class PlotPanel extends JPanel implements ActionListener { private JTabbedPane plotPane; @@ -23,8 +34,55 @@ JTabbedPane getPlotPane() { return plotPane; } + + /** + * Get the indices of the current selected tabs. + * @return The indices of the current tabs. + */ + int[] getSelectedTabs() { + int[] indices = new int[2]; + indices[0] = plotPane.getSelectedIndex(); + Component component = plotPane.getSelectedComponent(); + if (component instanceof JTabbedPane) { + indices[1] = ((JTabbedPane)component).getSelectedIndex(); + } + return indices; + } + + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(Commands.SAVE_SELECTED_PLOTS)) { + int[] indices = getSelectedTabs(); + IPlotter plotter = MonitoringPlotFactory.getPlotterRegistry().find(indices[0], indices[1]); + if (plotter != null) { + savePlotter(plotter); + } else { + DialogUtil.showErrorDialog(this, "Error Finding Plots", "No plots found in selected tab."); + } + } + } + + static final String DEFAULT_FORMAT = "png"; + void savePlotter(IPlotter plotter) { + JFileChooser fc = new JFileChooser(); + fc.setAcceptAllFileFilterUsed(false); + fc.setDialogTitle("Save Plots - " + plotter.title()); + fc.setCurrentDirectory(new File(".")); + int r = fc.showSaveDialog(this); + if (r == JFileChooser.APPROVE_OPTION) { + String path = fc.getSelectedFile().getPath(); + if (path.lastIndexOf(".") == -1) { + path += "." + DEFAULT_FORMAT; + } + try { + plotter.writeToFile(path); + } catch (IOException e) { + e.printStackTrace(); + DialogUtil.showErrorDialog(this, "Error Saving Plots", "There was an error saving the plots."); + } + } + } void reset() { - plotPane.removeAll(); - } + plotPane.removeAll(); + } } Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java (added) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java Sat Mar 14 12:37:17 2015 @@ -0,0 +1,147 @@ +/** + * + */ +package org.hps.monitoring.application; + +import java.awt.Component; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.DefaultTableModel; + +import org.hps.monitoring.application.model.SystemStatusTableModel; +import org.hps.monitoring.subsys.StatusCode; +import org.hps.monitoring.subsys.Subsystem; +import org.hps.monitoring.subsys.SystemStatus; +import org.hps.monitoring.subsys.SystemStatusImpl; +import org.hps.monitoring.subsys.SystemStatusListener; + +/** + * This is a table that shows every system status change in a different row. + * + * @author Jeremy McCormick <[log in to unmask]> + */ +public class SystemStatusEventsTable extends JTable { + + SystemStatusEventsTableModel tableModel = new SystemStatusEventsTableModel(); + + SystemStatusEventsTable() { + setModel(tableModel); + + // Date formatting. + getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer() { + + final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS"); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value instanceof Date) { + value = dateFormat.format(value); + } + return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } + }); + + // Rendering of system status cells using different background colors. + getColumnModel().getColumn(2).setCellRenderer(new DefaultTableCellRenderer() { + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { + + // Cells are by default rendered as a JLabel. + JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); + + // Color code the cell by its status. + StatusCode statusCode = StatusCode.valueOf((String) value); + label.setBackground(statusCode.getColor()); + return label; + } + }); + } + + void registerListener() { + } + + static class SystemStatusEventsTableModel extends DefaultTableModel implements SystemStatusListener { + + List<SystemStatus> statuses = new ArrayList<SystemStatus>(); + + String[] columnNames = { "Date", "Subsystem", "Status Code", "Description", "Message" }; + Class<?>[] columnClasses = { Date.class, Subsystem.class, SystemStatus.class, String.class, String.class }; + + SystemStatusEventsTableModel() { + } + + @Override + public String getColumnName(int column) { + return columnNames[column]; + } + + @Override + public Class<?> getColumnClass(int column) { + return columnClasses[column]; + } + + /** + * Update the table with status changes. + * @param status The system status. + */ + @Override + public void statusChanged(SystemStatus status) { + SystemStatus newStatus = new SystemStatusImpl(status); + statuses.add(newStatus); + fireTableDataChanged(); + } + + /** + * Register the listener on this status. + * @param status The system status. + */ + void addSystemStatus(SystemStatus status) { + status.addListener(this); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public int getRowCount() { + if (statuses != null) { + return statuses.size(); + } else { + return 0; + } + } + + @Override + public Object getValueAt(int row, int column) { + SystemStatus status = statuses.get(row); + switch (column) { + case 0: + return new Date(status.getLastChangedMillis()); + case 1: + return status.getSubsystem(); + case 2: + return status.getStatusCode(); + case 3: + return status.getDescription(); + case 4: + return status.getMessage(); + default: + return null; + } + } + + public void clear() { + this.statuses.clear(); + this.setRowCount(0); + } + } +} Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java (added) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java Sat Mar 14 12:37:17 2015 @@ -0,0 +1,51 @@ +/** + * + */ +package org.hps.monitoring.application; + +import java.awt.BorderLayout; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; + +import org.hps.monitoring.application.SystemStatusEventsTable.SystemStatusEventsTableModel; +import org.hps.monitoring.subsys.SystemStatus; + +/** + * This is a panel showing the two tables for viewing the system statuses, + * one showing the current state of all system status monitors and the other + * all system status change events. + * + * @author Jeremy McCormick <[log in to unmask]> + */ +public class SystemStatusPanel extends JPanel { + + SystemStatusTable statusTable = new SystemStatusTable(); + SystemStatusEventsTable eventsTable = new SystemStatusEventsTable(); + + SystemStatusPanel() { + super(new BorderLayout()); + JSplitPane splitPane = new JSplitPane( + JSplitPane.VERTICAL_SPLIT, + new JScrollPane(statusTable), + new JScrollPane(eventsTable)); + splitPane.setDividerLocation(50); + add(splitPane, + BorderLayout.CENTER); + } + + void addSystemStatus(SystemStatus status) { + // Register listeners of table models on this status. + statusTable.getTableModel().addSystemStatus(status); + eventsTable.tableModel.addSystemStatus(status); + } + + void clear() { + // Clear the system status monitor table. + statusTable.getTableModel().clear(); + + // Clear the system status events table. + ((SystemStatusEventsTableModel)eventsTable.getModel()).clear(); + } +} Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusTable.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusTable.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/SystemStatusTable.java Sat Mar 14 12:37:17 2015 @@ -1,6 +1,5 @@ package org.hps.monitoring.application; -import java.awt.Color; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -17,8 +16,7 @@ import org.hps.monitoring.subsys.StatusCode; /** - * A GUI window for showing changes to {@link org.hps.monitoring.subsys.SystemStatus} objects using - * a <code>JTable</code>. + * This table shows the current state of {@link org.hps.monitoring.subsys.SystemStatus} objects. */ class SystemStatusTable extends JTable { @@ -37,28 +35,7 @@ // Color code the cell by its status. StatusCode statusCode = StatusCode.valueOf((String) value); - if (statusCode.ordinal() >= StatusCode.ERROR.ordinal()) { - // Any type of error is red. - label.setBackground(Color.RED); - } else if (statusCode.equals(StatusCode.WARNING)) { - // Warnings are yellow. - label.setBackground(Color.YELLOW); - } else if (statusCode.equals(StatusCode.OKAY)) { - // Okay is green. - label.setBackground(Color.GREEN); - } else if (statusCode.equals(StatusCode.OFFLINE)) { - // Offline is orange. - label.setBackground(Color.ORANGE); - } else if (statusCode.equals(StatusCode.UNKNOWN)) { - // Unknown is gray. - label.setBackground(Color.GRAY); - } else if (statusCode.equals(StatusCode.CLEARED)) { - // Cleared is light gray. - label.setBackground(Color.LIGHT_GRAY); - } else { - // Default is white, though this shouldn't happen! - label.setBackground(Color.WHITE); - } + label.setBackground(statusCode.getColor()); return label; } }); Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/RunnableEtStation.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/RunnableEtStation.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/RunnableEtStation.java Sat Mar 14 12:37:17 2015 @@ -26,7 +26,6 @@ */ public abstract class RunnableEtStation implements Runnable { - protected EtSystem system; protected EtStation station; protected EtAttachment attachment; protected boolean disconnect = false; @@ -76,7 +75,7 @@ try { for (;;) { // Get the next array of events from the server. - EtEvent[] events = system.getEvents( + EtEvent[] events = config.system.getEvents( attachment, Mode.SLEEP, Modify.NOTHING, 0, config.readEvents); // Process the events. @@ -96,7 +95,7 @@ System.err.println("Error running " + this.config.name + " ..."); e.printStackTrace(); } finally { - if (system.alive()) { + if (config.system.alive()) { System.out.println(this.config.name + " is disconnecting ..."); disconnect(); System.out.println("disconnected " + this.config.name); @@ -123,21 +122,23 @@ } // Create station and attach to the ET system. - EtStation station = system.createStation(stationConfig, config.name, config.order); - attachment = system.attach(station); + EtStation station = config.system.createStation(stationConfig, config.name, config.order); + attachment = config.system.attach(station); } catch (Exception e) { + System.err.println("Error while running setup of " + config.name + " ..."); + e.printStackTrace(); // Any errors during setup are rethrown. throw new RuntimeException(e); } } public synchronized void disconnect() { - if (system.alive()) { + if (config.system.alive()) { if (attachment.isUsable()) { try { - system.wakeUpAll(station); - system.detach(attachment); + config.system.wakeUpAll(station); + config.system.detach(attachment); } catch (IOException | EtException | EtClosedException | EtDeadException e) { e.printStackTrace(); }