Author: [log in to unmask] Date: Mon Mar 30 17:54:19 2015 New Revision: 2631 Log: Add support for recent files menu. Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/ToolbarPanel.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/DataSourceComboBox.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/MenuBar.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/model/AbstractModel.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/Configuration.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.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 Mon Mar 30 17:54:19 2015 @@ -15,6 +15,7 @@ // File open and close static final String OPEN_FILE = "openFile"; static final String CLOSE_FILE = "closeFile"; + static final String RECENT_FILE_SELECTED = "recentFileSelected"; // Window static final String MAXIMIZE_WINDOW = "maximizeWindow"; Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java Mon Mar 30 17:54:19 2015 @@ -1,5 +1,6 @@ package org.hps.monitoring.application; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -8,7 +9,10 @@ import java.io.File; import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListCellRenderer; import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.ListCellRenderer; import org.hps.monitoring.application.DataSourceComboBox.DataSourceItem; import org.hps.monitoring.application.model.ConfigurationModel; @@ -17,13 +21,13 @@ import org.hps.record.enums.DataSourceType; /** + * This is a combo box that shows the current data source such as an LCIO file, EVIO file or ET ring. + * It can also be used to selected a new data source for the new session. * <p> - * This is a combo box that shows and can be used to select the current data source - * such as an LCIO file, EVIO file or ET ring. + * The way this works is kind of odd because it is not directly connected to an event loop, so it must + * catch changes to the configuration and update its items accordingly. * <p> - * The way this works is kind of funky because it is not directly connected to an - * event loop, so it must catch changes to the configuration and update its - * items accordingly. + * A single ET item is kept in the list and updated as changes are made to the global configuration. * * @author Jeremy McCormick <[log in to unmask]> */ @@ -34,15 +38,34 @@ static class DataSourceItem { - String name; - DataSourceType type; - - DataSourceItem(String name, DataSourceType type) { + private String name; + private String path; + private DataSourceType type; + + DataSourceItem(String path, String name, DataSourceType type) { + if (path == null) { + throw new IllegalArgumentException("path is null"); + } + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + if (type == null) { + throw new IllegalArgumentException("type is null"); + } this.type = type; this.name = name; + this.path = path; } public String toString() { + return name; + } + + public String getPath() { + return path; + } + + public String getName() { return name; } @@ -51,23 +74,42 @@ return false; } DataSourceItem otherItem = (DataSourceItem) object; - if (this.name == otherItem.name && this.type == otherItem.type) + if (this.name == otherItem.name && this.path == otherItem.path && this.type == otherItem.type) { return true; - return false; - } - } - + } else { + return false; + } + } + } + + @SuppressWarnings({ "rawtypes", "serial", "unchecked" }) DataSourceComboBox(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel) { addActionListener(this); setActionCommand(Commands.DATA_SOURCE_CHANGED); - setPreferredSize(new Dimension(400, this.getPreferredSize().height)); + setPreferredSize(new Dimension(510, this.getPreferredSize().height)); setEditable(false); this.configurationModel = configurationModel; connectionModel.addPropertyChangeListener(this); configurationModel.addPropertyChangeListener(this); + + ListCellRenderer renderer = new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList<?> list, + Object value, int index, boolean isSelected, + boolean cellHasFocus) { + if (value instanceof DataSourceItem) { + setToolTipText(((DataSourceItem)value).getPath()); + } else { + setToolTipText(null); + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + + }; + this.setRenderer(renderer); } - boolean contains(DataSourceItem item) { + boolean containsItem(DataSourceItem item) { return ((DefaultComboBoxModel<DataSourceItem>) getModel()).getIndexOf(item) != -1; } @@ -83,11 +125,11 @@ setEnabled(false); } } else if (evt.getPropertyName().equals(ConfigurationModel.DATA_SOURCE_PATH_PROPERTY)) { - if (configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_TYPE_PROPERTY)) { + if (configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_TYPE_PROPERTY)) { String path = configurationModel.getDataSourcePath(); - DataSourceType type = getDataSourceType(path); + DataSourceType type = DataSourceType.getDataSourceType(path); if (type.isFile()) { - DataSourceItem item = findItem(path, type); + DataSourceItem item = findItem(path); if (item == null) { item = addDataSourceItem(path, type); } @@ -100,12 +142,12 @@ if (configurationModel.getDataSourceType() == DataSourceType.ET_SERVER) { DataSourceItem item = findEtItem(); if (item == null) { - item = new DataSourceItem(configurationModel.getEtPath(), DataSourceType.ET_SERVER); + item = new DataSourceItem(configurationModel.getEtPath(), configurationModel.getEtPath(), DataSourceType.ET_SERVER); } setSelectedItem(item); } else { if (configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_PATH_PROPERTY)) { - DataSourceItem item = findItem(configurationModel.getDataSourcePath(), configurationModel.getDataSourceType()); + DataSourceItem item = findItem(configurationModel.getDataSourcePath()); if (item == null) { item = addDataSourceItem(configurationModel.getDataSourcePath(), configurationModel.getDataSourceType()); } @@ -124,14 +166,10 @@ } } - static DataSourceType getDataSourceType(String path) { - if (path.endsWith(".slcio")) { - return DataSourceType.LCIO_FILE; - } else if (new File(path).getName().contains(".evio")) { - return DataSourceType.EVIO_FILE; - } else { - return DataSourceType.ET_SERVER; - } + @Override + public void setSelectedItem(Object object) { + super.setSelectedItem(object); + this.setToolTipText(((DataSourceItem)object).getPath()); } public void actionPerformed(ActionEvent evt) { @@ -143,7 +181,7 @@ if (item != null) { configurationModel.setDataSourceType(item.type); if (item.type != DataSourceType.ET_SERVER) { - configurationModel.setDataSourcePath(item.name); + configurationModel.setDataSourcePath(item.getPath()); } } } finally { @@ -153,22 +191,20 @@ } public void addItem(DataSourceItem item) { - // Do not add invalid looking items. - if (item.name == null || item.name.length() == 0) { + if (containsItem(item)) { return; } - // Do not add duplicates. - if (!contains(item)) { + if (findItem(item.getPath()) == null) { super.addItem(item); } } - DataSourceItem findItem(String path, DataSourceType type) { + DataSourceItem findItem(String path) { for (int i = 0; i < this.getItemCount(); i++) { DataSourceItem item = this.getItemAt(i); - if (item.type == type && item.name == path) { + if (item.getPath().equals(path)) { return item; - } + } } return null; } @@ -184,7 +220,7 @@ } DataSourceItem addDataSourceItem(String path, DataSourceType type) { - DataSourceItem newItem = new DataSourceItem(path, type); + DataSourceItem newItem = new DataSourceItem(path, new File(path).getName(), type); addItem(newItem); return newItem; } @@ -192,7 +228,7 @@ void updateEtItem() { DataSourceItem item = findEtItem(); if (item == null) { - item = new DataSourceItem(configurationModel.getEtPath(), DataSourceType.ET_SERVER); + item = new DataSourceItem(configurationModel.getEtPath(), configurationModel.getEtPath(), DataSourceType.ET_SERVER); addItem(item); } else { item.name = configurationModel.getEtPath(); 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 Mon Mar 30 17:54:19 2015 @@ -219,6 +219,8 @@ */ void setupLoop(ConfigurationModel configurationModel) { + logger.config("setting up record loop ..."); + CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration() .setStopOnEndRun(configurationModel.getDisconnectOnEndRun()) .setStopOnErrors(configurationModel.getDisconnectOnError()) @@ -227,6 +229,9 @@ .setEtConnection(sessionState.connection) .setFilePath(configurationModel.getDataSourcePath()) .setLCSimEventBuilder(sessionState.eventBuilder); + + logger.config("data source path is " + configurationModel.getDataSourcePath()); + logger.config("data source type is " + configurationModel.getDataSourceType()); if (configurationModel.hasValidProperty(ConfigurationModel.MAX_EVENTS_PROPERTY)) { long maxEvents = configurationModel.getMaxEvents(); @@ -238,39 +243,41 @@ // Add all Drivers from the JobManager. for (Driver driver : sessionState.jobManager.getDriverExecList()) { loopConfig.add(driver); - logger.config("added Driver " + driver.getName() + " to job"); + logger.config("added Driver " + driver.getName()); } // Using ET server? if (configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) { // ET system monitor. - logger.config("added EtSystemMonitor to job"); + logger.config("added EtSystemMonitor"); loopConfig.add(new EtSystemMonitor()); // ET system strip charts. - logger.config("added EtSystemStripCharts to job"); + logger.config("added EtSystemStripCharts"); loopConfig.add(new EtSystemStripCharts()); } // Add extra CompositeRecordProcessors to the loop config. for (CompositeRecordProcessor processor : sessionState.processors) { loopConfig.add(processor); - logger.config("added extra processor " + processor.getClass().getSimpleName() + " to job"); + logger.config("added extra processor " + processor.getClass().getSimpleName()); } // Add extra Drivers to the loop config. for (Driver driver : sessionState.drivers) { loopConfig.add(driver); - logger.config("added extra Driver " + driver.getName() + " to job"); + logger.config("added extra Driver " + driver.getName()); } // Enable conditions system activation from EVIO event data in case the PRESTART is missed. + loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName())); 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); + + logger.config("record loop is setup"); } /** Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MenuBar.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MenuBar.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MenuBar.java Mon Mar 30 17:54:19 2015 @@ -5,6 +5,7 @@ import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.List; import javax.swing.JMenu; import javax.swing.JMenuBar; @@ -20,15 +21,33 @@ * * @author Jeremy McCormick <[log in to unmask]> */ +@SuppressWarnings("serial") class MenuBar extends JMenuBar implements PropertyChangeListener, ActionListener { + + ConfigurationModel configurationModel; JMenuItem closeFileItem; JMenuItem openFileItem; JMenu settingsMenu; JMenuItem logItem; JMenuItem serverItem; - ConfigurationModel configurationModel; - + JMenu recentFilesMenu; + + class RecentFileItem extends JMenuItem { + + String path; + + RecentFileItem(String path, int mnemonic) { + setText((mnemonic - KeyEvent.VK_0) + " " + path); + setMnemonic(mnemonic); + this.path = path; + } + + String getPath() { + return path; + } + } + MenuBar(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel, ActionListener listener) { this.configurationModel = configurationModel; @@ -62,6 +81,11 @@ exitItem.setToolTipText("Exit from the application"); fileMenu.add(exitItem); + recentFilesMenu = new JMenu("RecentFiles"); + recentFilesMenu.setMnemonic(KeyEvent.VK_R); + recentFilesMenu.setToolTipText("List of recent data files"); + fileMenu.add(recentFilesMenu); + settingsMenu = new JMenu("Settings"); settingsMenu.setMnemonic(KeyEvent.VK_S); add(settingsMenu); @@ -127,7 +151,7 @@ toolsMenu.add(screenshotItem); logItem = new JMenuItem("Log to File ..."); - logItem.setMnemonic(KeyEvent.VK_R); + logItem.setMnemonic(KeyEvent.VK_L); logItem.setActionCommand(Commands.LOG_TO_FILE); logItem.addActionListener(listener); logItem.setEnabled(true); @@ -168,7 +192,7 @@ defaultsItem.addActionListener(listener); defaultsItem.setEnabled(true); defaultsItem.setToolTipText("Restore the window defaults"); - windowMenu.add(defaultsItem); + windowMenu.add(defaultsItem); } @Override @@ -193,7 +217,10 @@ logItem.setActionCommand(Commands.LOG_TO_FILE); logItem.setToolTipText("Log messages to a file"); } - } + } else if (evt.getPropertyName().equals(ConfigurationModel.RECENT_FILES_PROPERTY)) { + setRecentFiles(configurationModel.getRecentFilesList()); + } + } finally { configurationModel.addPropertyChangeListener(this); } @@ -207,8 +234,26 @@ } else { closeFileItem.setEnabled(false); } + } + } + + void setRecentFiles(List<String> recentFiles) { + recentFilesMenu.removeAll(); + int fileMnemonic = 48; /* starts at KeyEvent.VK_0 */ + for (String recentFile : recentFiles) { + RecentFileItem recentFileItem = new RecentFileItem(recentFile, fileMnemonic); + recentFileItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String recentFile = ((RecentFileItem) e.getSource()).getPath(); + DataSourceType dst = DataSourceType.getDataSourceType(recentFile); + configurationModel.setDataSourcePath(recentFile); + configurationModel.setDataSourceType(dst); + } + }); + recentFilesMenu.add(recentFileItem); + ++fileMnemonic; } - } + } void startAIDAServer() { serverItem.setActionCommand(Commands.STOP_AIDA_SERVER); 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 Mon Mar 30 17:54:19 2015 @@ -46,9 +46,9 @@ import org.hps.monitoring.application.util.ErrorHandler; import org.hps.monitoring.application.util.EvioFileFilter; import org.hps.monitoring.application.util.TableExporter; +import org.hps.monitoring.plotting.ExportPdf; import org.hps.monitoring.plotting.MonitoringAnalysisFactory; import org.hps.monitoring.plotting.MonitoringPlotFactory; -import org.hps.monitoring.plotting.ExportPdf; import org.hps.monitoring.subsys.SystemStatus; import org.hps.monitoring.subsys.SystemStatusRegistry; import org.hps.record.composite.CompositeRecordProcessor; @@ -56,7 +56,6 @@ import org.lcsim.conditions.ConditionsListener; import org.lcsim.util.Driver; import org.lcsim.util.aida.AIDA; -import org.lcsim.util.aida.PDFWriter; import org.lcsim.util.log.DefaultLogFormatter; /** @@ -91,10 +90,7 @@ final RunModel runModel = new RunModel(); final ConfigurationModel configurationModel = new ConfigurationModel(); final ConnectionStatusModel connectionModel = new ConnectionStatusModel(); - - // The global configuration settings. - Configuration configuration; - + // The default configuration resource embedded in the jar. static final String DEFAULT_CONFIGURATION = "/org/hps/monitoring/config/default_config.prop"; @@ -206,17 +202,14 @@ // Setup AIDA plotting and connect it to the GUI. setupAida(); - - // TODO: Make sure the configuration loading here is working properly!!! - - // Always load the default configuration first. - this.configuration = new Configuration(DEFAULT_CONFIGURATION); - loadConfiguration(this.configuration); - - // Overlay the user configuration if one was specified. + + // Load the default configuration. + loadConfiguration(new Configuration(DEFAULT_CONFIGURATION), false); + if (userConfiguration != null) { - loadConfiguration(userConfiguration); - } + // Load user configuration. + loadConfiguration(userConfiguration, true); + } // Enable the GUI now that initialization is complete. frame.setEnabled(true); @@ -357,19 +350,23 @@ * This method sets the configuration on the model, which fires a change for every property. * @param configuration The new configuration. */ - void loadConfiguration(Configuration configuration) { - - this.configuration = configuration; - - // HACK: Clear data source combo box for new config. - frame.dataSourceComboBox.removeAllItems(); - - // Set the Configuration on the ConfigurationModel which will trigger all the PropertyChangelListeners. - configurationModel.setConfiguration(this.configuration); - if (this.configuration.getFile() != null) - logger.config("loaded config from file " + this.configuration.getFile().getPath()); + void loadConfiguration(Configuration configuration, boolean merge) { + + if (merge) { + // This will merge in additional properties so that default or current settings are preserved. + configurationModel.merge(configuration); + } else { + // HACK: Clear data source combo box for clean configuration. + frame.toolbarPanel.dataSourceComboBox.removeAllItems(); + + // This will reset all configuration properties. + configurationModel.setConfiguration(configuration); + } + + if (configuration.getFile() != null) + logger.config("loaded config from file " + configuration.getFile().getPath()); else - logger.config("loaded config from resource " + this.configuration.getResourcePath()); + logger.config("loaded config from resource " + configuration.getResourcePath()); } /** @@ -540,8 +537,7 @@ * Load default application settings. */ void loadDefaultSettings() { - configuration = new Configuration(MonitoringApplication.DEFAULT_CONFIGURATION); - configurationModel.setConfiguration(configuration); + loadConfiguration(new Configuration(MonitoringApplication.DEFAULT_CONFIGURATION), false); DialogUtil.showInfoDialog(frame, "Default Configuration Loaded", "The default configuration was loaded."); logger.config("default settings loaded"); } @@ -583,6 +579,8 @@ configurationModel.setDataSourcePath(filePath); configurationModel.setDataSourceType(type); + configurationModel.addRecentFile(filePath); + logger.config("set new data source " + filePath + " with type " + type); } } @@ -597,7 +595,7 @@ int r = fc.showSaveDialog(frame); if (r == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); - configuration.writeToFile(f); + configurationModel.getConfiguration().writeToFile(f); logger.info("saved configuration to file: " + f.getPath()); DialogUtil.showInfoDialog(frame, "Settings Saved", "Settings were saved successfully."); } @@ -613,7 +611,7 @@ int r = fc.showDialog(frame, "Load ..."); if (r == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); - loadConfiguration(new Configuration(f)); + loadConfiguration(new Configuration(f), true); logger.info("loaded configuration from file: " + f.getPath()); DialogUtil.showInfoDialog(frame, "Settings Loaded", "Settings were loaded successfully."); } @@ -646,9 +644,9 @@ */ void closeFile() { if (!configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) { - DataSourceItem item = (DataSourceItem) frame.dataSourceComboBox.getSelectedItem(); - if (item.name.equals(configurationModel.getDataSourcePath())) { - frame.dataSourceComboBox.removeItem(frame.dataSourceComboBox.getSelectedItem()); + DataSourceItem item = (DataSourceItem) frame.toolbarPanel.dataSourceComboBox.getSelectedItem(); + if (item.getPath().equals(configurationModel.getDataSourcePath())) { + frame.toolbarPanel.dataSourceComboBox.removeItem(frame.toolbarPanel.dataSourceComboBox.getSelectedItem()); } } } 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 Mon Mar 30 17:54:19 2015 @@ -2,40 +2,36 @@ import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.FlowLayout; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import javax.swing.JFrame; import javax.swing.JPanel; -import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; -import javax.swing.SwingConstants; /** * This class instantiates the primary GUI components of the monitoring application. * * @author Jeremy McCormick <[log in to unmask]> */ +@SuppressWarnings("serial") class MonitoringApplicationFrame extends JFrame { EventDashboard dashboardPanel; PlotPanel plotPanel; PlotInfoPanel plotInfoPanel; LogPanel logPanel; - JPanel buttonsPanel; TriggerDiagnosticsPanel triggerPanel; ConditionsPanel conditionsPanel; SystemStatusPanel systemStatusPanel; + ToolbarPanel toolbarPanel; MenuBar menu; JSplitPane mainSplitPane; JSplitPane rightSplitPane; JSplitPane leftSplitPane; - - DataSourceComboBox dataSourceComboBox; - + SettingsDialog settingsDialog; static final Rectangle BOUNDS = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); @@ -60,31 +56,9 @@ contentPanel.setPreferredSize(new Dimension(PIXEL_WIDTH_MAX, PIXEL_HEIGHT_MAX)); // Create the top panel. - JPanel topPanel = new JPanel(); - topPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 0)); - contentPanel.add(topPanel, BorderLayout.NORTH); - - // Create the connection status panel. - JPanel connectionPanel = new ConnectionStatusPanel(application.connectionModel); - topPanel.add(connectionPanel); - - // Add vertical separator. - JSeparator sep = new JSeparator(SwingConstants.VERTICAL); - sep.setPreferredSize(new Dimension(5, topPanel.getPreferredSize().height)); - topPanel.add(sep); - - // Create the buttons panel. - buttonsPanel = new EventButtonsPanel(application.connectionModel, application); - topPanel.add(buttonsPanel); - - // Add vertical separator. - sep = new JSeparator(SwingConstants.VERTICAL); - topPanel.add(sep); - - // Add the data source combo box. - dataSourceComboBox = new DataSourceComboBox(application.configurationModel, application.connectionModel); - topPanel.add(dataSourceComboBox); - + toolbarPanel = new ToolbarPanel(application.configurationModel, application.connectionModel, application); + contentPanel.add(toolbarPanel, BorderLayout.NORTH); + // Create the bottom panel. JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BorderLayout()); @@ -146,7 +120,7 @@ // Create the menu bar. menu = new MenuBar(application.configurationModel, application.connectionModel, application); setJMenuBar(menu); - dataSourceComboBox.addActionListener(menu); + toolbarPanel.dataSourceComboBox.addActionListener(menu); // Setup the settings dialog box (invisible until activated). settingsDialog = new SettingsDialog(application.configurationModel, application); Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/ToolbarPanel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/ToolbarPanel.java (added) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/ToolbarPanel.java Mon Mar 30 17:54:19 2015 @@ -0,0 +1,65 @@ +package org.hps.monitoring.application; + +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionListener; + +import javax.swing.JPanel; + +import org.hps.monitoring.application.model.ConfigurationModel; +import org.hps.monitoring.application.model.ConnectionStatusModel; + +/** + * A GUI component for the top-level toolbar of the monitoring app. + * + * @author Jeremy McCormick <[log in to unmask]> + */ +public class ToolbarPanel extends JPanel { + + DataSourceComboBox dataSourceComboBox; + JPanel buttonsPanel; + + ToolbarPanel(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel, ActionListener listener) { + + setLayout(new FlowLayout(FlowLayout.LEFT)); + + JPanel containerPanel = new JPanel(); + containerPanel.setLayout(new GridBagLayout()); + + // Create the connection status panel. + GridBagConstraints gbs = new GridBagConstraints(); + gbs.anchor = GridBagConstraints.WEST; + gbs.gridx = 0; + gbs.gridy = 0; + gbs.weightx = 0.5; + gbs.fill = GridBagConstraints.BOTH; + gbs.insets = new Insets(10, 0, 0, 10); + JPanel connectionPanel = new ConnectionStatusPanel(connectionModel); + containerPanel.add(connectionPanel, gbs); + + // Create the buttons panel. + buttonsPanel = new EventButtonsPanel(connectionModel, listener); + gbs.anchor = GridBagConstraints.WEST; + gbs.gridx = 1; + gbs.gridy = 0; + gbs.weightx = 0.5; + gbs.fill = GridBagConstraints.BOTH; + gbs.insets = new Insets(0, 0, 0, 10); + containerPanel.add(buttonsPanel, gbs); + + // Add the data source combo box. + dataSourceComboBox = new DataSourceComboBox(configurationModel, connectionModel); + gbs = new GridBagConstraints(); + gbs.anchor = GridBagConstraints.WEST; + gbs.gridx = 2; + gbs.gridy = 0; + gbs.weightx = 1.0; + gbs.fill = GridBagConstraints.HORIZONTAL; + containerPanel.add(dataSourceComboBox, gbs); + + add(containerPanel); + } + +} Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/AbstractModel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/AbstractModel.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/AbstractModel.java Mon Mar 30 17:54:19 2015 @@ -7,6 +7,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import javassist.Modifier; @@ -41,8 +43,8 @@ abstract public String[] getPropertyNames(); - public void fireModelChanged() { - propertyLoop: for (String property : getPropertyNames()) { + void firePropertiesChanged(Collection<String> properties) { + propertyLoop: for (String property : properties) { Method getMethod = null; for (Method method : getClass().getMethods()) { if (method.getName().equals("get" + property)) { @@ -50,6 +52,7 @@ break; } } + //System.out.println(getMethod.getName()); try { Object value = null; try { @@ -65,6 +68,7 @@ System.err.println("The key " + property + " is not set in the configuration."); continue propertyLoop; } else { + e.printStackTrace(); throw new RuntimeException(e); } } @@ -76,9 +80,14 @@ } } } catch (IllegalAccessException | IllegalArgumentException e) { + e.printStackTrace(); throw new RuntimeException(e); } } + } + + public void fireModelChanged() { + firePropertiesChanged(Arrays.asList(getPropertyNames())); } /** Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/Configuration.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/Configuration.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/Configuration.java Mon Mar 30 17:54:19 2015 @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import java.util.Set; /** * This class provides a list of key, value pairs backed by a <code>Properties</code> object. The @@ -193,6 +194,25 @@ * Convert this object to a string by printing out its properties list. */ public String toString() { - return properties.toString(); + return properties.toString(); + } + + /** + * Get the property keys. + * @return The collection of property keys. + */ + public Set<String> getKeys() { + return properties.stringPropertyNames(); + } + + /** + * Merge in values from another configuration into this one which will override + * properties that already exist with new values. + * @param configuration The configuration with the properties to merge. + */ + void merge(Configuration configuration) { + for (String property : configuration.getKeys()) { + this.set(property, configuration.get(property)); + } } } Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java Mon Mar 30 17:54:19 2015 @@ -1,5 +1,7 @@ package org.hps.monitoring.application.model; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import org.hps.record.enums.DataSourceType; @@ -28,6 +30,7 @@ public static final String LOG_LEVEL_FILTER_PROPERTY = "LogLevelFilter"; public static final String LOG_TO_FILE_PROPERTY = "LogToFile"; public static final String MAX_EVENTS_PROPERTY = "MaxEvents"; + public static final String RECENT_FILES_PROPERTY = "RecentFiles"; public static final String STEERING_TYPE_PROPERTY = "SteeringType"; public static final String STEERING_FILE_PROPERTY = "SteeringFile"; public static final String STEERING_RESOURCE_PROPERTY = "SteeringResource"; @@ -79,7 +82,7 @@ return Level.parse(configuration.get(LOG_LEVEL_PROPERTY)); } - public void setLogLevel(Level level) { + public void setLogLevel(Level level) { Level oldValue = getLogLevel(); configuration.set(LOG_LEVEL_PROPERTY, level.getName()); firePropertyChange(LOG_LEVEL_PROPERTY, oldValue, getLogLevel()); @@ -199,7 +202,11 @@ } public DataSourceType getDataSourceType() { - return DataSourceType.valueOf(configuration.get(DATA_SOURCE_TYPE_PROPERTY)); + if (configuration.checkKey(DATA_SOURCE_TYPE_PROPERTY)) { + return DataSourceType.valueOf(configuration.get(DATA_SOURCE_TYPE_PROPERTY)); + } else { + return null; + } } public void setDataSourceType(DataSourceType dataSourceType) { @@ -217,6 +224,14 @@ configuration.set(DATA_SOURCE_PATH_PROPERTY, dataSourcePath); firePropertyChange(DATA_SOURCE_PATH_PROPERTY, oldValue, getDataSourcePath()); } + + /* + public void setDataSource(String dataSource) { + setDataSourcePath(dataSource); + DataSourceType dst = DataSourceType.getDataSourceType(dataSource); + setDataSourceType(dst); + } + */ public ProcessingStage getProcessingStage() { if (configuration.get(PROCESSING_STAGE_PROPERTY) == null) @@ -408,6 +423,52 @@ public String getAIDAServerName() { return configuration.get(AIDA_SERVER_NAME_PROPERTY); + } + + public String getRecentFiles() { + if (configuration.hasKey(RECENT_FILES_PROPERTY)) { + return configuration.get(RECENT_FILES_PROPERTY); + } else { + return null; + } + } + + public List<String> getRecentFilesList() { + List<String> recentFilesList = new ArrayList<String>(); + if (configuration.hasKey(RECENT_FILES_PROPERTY)) { + for (String recentFile : configuration.get(RECENT_FILES_PROPERTY).split("\n")) { + recentFilesList.add(recentFile); + } + } + return recentFilesList; + } + + public void addRecentFile(String recentFile) { + if (!configuration.checkKey(RECENT_FILES_PROPERTY)) { + configuration.set(RECENT_FILES_PROPERTY, recentFile); + firePropertyChange(RECENT_FILES_PROPERTY, null, recentFile); + } else { + List<String> recentFilesList = getRecentFilesList(); + if (!recentFilesList.contains(recentFile)) { + if (getRecentFilesList().size() >= 10) { + throw new IllegalArgumentException("Maximum number of recent files reached."); + } + String oldValue = configuration.get(RECENT_FILES_PROPERTY); + String recentFiles = oldValue + "\n" + recentFile; + configuration.set(RECENT_FILES_PROPERTY, recentFiles); + firePropertyChange(RECENT_FILES_PROPERTY, oldValue, recentFile); + } + } + + } + + public void setRecentFiles(String recentFiles) { + String oldValue = null; + if (configuration.checkKey(RECENT_FILES_PROPERTY)) { + oldValue = configuration.get(RECENT_FILES_PROPERTY); + } + configuration.set(RECENT_FILES_PROPERTY, recentFiles); + firePropertyChange(RECENT_FILES_PROPERTY, oldValue, configuration.get(RECENT_FILES_PROPERTY)); } public void remove(String property) { @@ -432,4 +493,13 @@ public String[] getPropertyNames() { return CONFIG_PROPERTIES; } + + public void fireModelChanged() { + firePropertiesChanged(configuration.getKeys()); + } + + public void merge(Configuration configuration) { + this.configuration.merge(configuration); + this.firePropertiesChanged(configuration.getKeys()); + } }