/* MontageFiltersPanel.java created 2008-02-03 * */ package org.signalml.app.view.montage; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; import javax.swing.AbstractAction; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.apache.log4j.Logger; import org.signalml.app.config.preset.managers.PredefinedTimeDomainFiltersPresetManager; import org.signalml.app.document.signal.SignalDocument; import org.signalml.app.model.montage.MontageFilterEnableTableModel; import org.signalml.app.model.montage.MontageFiltersTableModel; import org.signalml.app.util.IconUtils; import org.signalml.app.util.SwingUtils; import org.signalml.app.view.TablePopupMenuProvider; import org.signalml.app.view.common.components.ResolvableComboBox; import org.signalml.app.view.montage.filters.EditFFTSampleFilterDialog; import org.signalml.app.view.montage.filters.EditTimeDomainSampleFilterDialog; import org.signalml.domain.montage.Montage; import org.signalml.domain.montage.MontageChannel; import org.signalml.domain.montage.MontageSampleFilter; import org.signalml.domain.montage.filter.FFTSampleFilter; import org.signalml.domain.montage.filter.SampleFilterDefinition; import org.signalml.domain.montage.filter.SampleFilterType; import org.signalml.domain.montage.filter.TimeDomainSampleFilter; import org.signalml.exception.SanityCheckException; /** * Panel which allows to add, remove and edit filters associated with the. * * {@link Montage montage}. There filters can be either * {@link TimeDomainSampleFilter}s or {@link FFTSampleFilter}s. * <p> * This panel contains five subpanels: * <ul> * <li>the panel with the {@link #getFilteringEnabledCheckBox() check box} to * enable {@link Montage#isFiltered() signal filtering},</li> * <li>the panel with the {@link #getFiltersTable() table} with the list of * filters and two buttons: * <ul> * <li>the button to {@link #getEditFilterButton() edit} a filter,</li> * <li>the button to {@link #getRemoveFilterButton() remove} a filter,</li> * </ul> * </li> * <li>the panel which contains two buttons allowing to add a * {@link TimeDomainSampleFilter} to the list of filters: * <ul> * <li>the {@link #getAddTimeDomainFilterButton() button} and * {@link #getTimeDomainFilterTypeComboBox() combo-box} which adds the * predefined filter,</li> * <li>the {@link #getAddCustomTimeDomainFilterButton() button} which opens a * {@link #getEditTimeDomainSampleFilterDialog() dialog} to add a custom filter, * </li> * </ul> * </li> * <li>the panel which allows to add a {@link FFTSampleFilter} and contains a * {@link #getFftFilterTypeComboBox() combo-box} and a * {@link #getAddFFTFilterButton() button} do to it,</li> * <li>the panel with the {@link #getFilterExclusionTable() exclusion table}.</li> * </ul> * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe * Sp. z o.o. */ public class MontageFiltersPanel extends JPanel { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** the logger. */ protected static final Logger logger = Logger.getLogger(MontageFiltersPanel.class); /** * the dialog that is used when editing. {@link FFTSampleFilter * FFTSampleFilter's} parameters */ private EditFFTSampleFilterDialog editFFTSampleFilterDialog; /** * the dialog that is used when editing {@link TimeDomainSampleFilter} * parameters. */ private EditTimeDomainSampleFilterDialog editTimeDomainSampleFilterDialog; /** the {@link Montage montage} that is edited. */ private Montage montage; /** * <code>true</code> if there exists a {@link SignalDocument document} * associated with the {@link Montage montage}, <code>false</code> otherwise. */ private boolean signalBound; /** the sampling frequency of the signal (the number of samples per second). */ private float currentSamplingFrequency; /** * check box which states if the signal should be * {@link Montage#isFiltered() filtered}. */ private JCheckBox filteringEnabledCheckBox; /** * checkbox which can be used to enable/disable forward-backward * (filtfilt) filtering ({@link Montage#setFiltfiltEnabled(boolean)}). */ private JCheckBox filtfiltEnabledCheckBox; /** * the {@link MontageFiltersTableModel model} for the {@link #filtersTable}. */ private MontageFiltersTableModel filtersTableModel; /** * the {@link MontageFiltersTable table} with the list of filters associated * with the {@link #getMontage() montage}. */ private MontageFiltersTable filtersTable; /** the scroll pane for the {@link #getFiltersTable() filters table}. */ private JScrollPane filtersScrollPane; /** * the {@link MontageFilterEnableTableModel model} for the. * {@link #getFilterExclusionTable() filter exclusion table} */ private MontageFilterEnableTableModel filterExclusionTableModel; /** * the table which allows to select which {@link MontageChannel montage * channels} should not be {@link MontageSampleFilter filtered} by which * filter. */ private MontageFilterEnableTable filterExclusionTable; /** * the scroll pane for the {@link #getFilterExclusionTable() filter * exclusion table}. */ private JScrollPane filterExclusionScrollPane; /** * a {@link ResolvableComboBox} allowing to select a predefined. * {@link TimeDomainSampleFilter} to be added to the signal chain */ private JComboBox timeDomainFilterTypeComboBox; /** * a {@link JComboBox} allowing to select the initial parameters of the * {@link FFTSampleFilter} shown in the {@link EditFFTSampleFilterDialog}. */ private JComboBox fftFilterTypeComboBox; /** * action which adds a {@link TimeDomainSampleFilter} and is invoked after * pressing the {@link #getAddTimeDomainFilterButton() * addTimeDomainFilterButton}. */ private AddTimeDomainFilterAction addTimeDomainFilterAction; /** * action which adds a {@link TimeDomainSampleFilter}, displays a. * {@link EditTimeDomainSampleFilterDialog} and is invoked after pressing * the {@link #getAddCustomTimeDomainFilterButton() * addCustomTimeDomainFilterButton} */ private AddCustomTimeDomainFilterAction addCustomTimeDomainFilterAction; /** * action which adds a {@link FFTSampleFilter} and is invoked after pressing * the {@link #getAddFFTFilterButton() addFFTFilterButton}. */ private AddFFTFilterAction addFFTFilterAction; /** * action which displays a {@link EditTimeDomainSampleFilterDialog} and is * invoked after pressing the {@link #getEditFilterButton() * editFilterButton}. */ private EditFilterAction editFilterAction; /** * action which removes a selected {@link MontageSampleFilter filter} from * the list of filters and is invoked after pressing the * {@link #getRemoveFilterButton() removeFilterButton}. */ private RemoveFilterAction removeFilterAction; /** * action which removes the exclusions of the filters. */ private SelectAllFiltersAction selectAllFiltersAction; /** * a button which can be used to add a predefined * {@link TimeDomainSampleFilter} to the list of filters. */ private JButton addTimeDomainFilterButton; /** * a button allowing to add a custom-designed filter to the list of filters. */ private JButton addCustomTimeDomainFilterButton; /** * a button which can be used to add a predefined {@link FFTSampleFilter} to * the list of filters. */ private JButton addFFTFilterButton; /** a button allowing to edit the selected filter's parameters. */ private JButton editFilterButton; /** * a button allowing to delete currently selected filter from the list of * filters. */ private JButton removeFilterButton; /** * a button allowing to clear all selections in the. * {@link #getFilterExclusionTable() filterExclusionTable} */ private JButton selectAllFiltersButton; /** * the manager at which predefined {@link TimeDomainSampleFilter * TimeDomainSampleFilters} are stored. */ private PredefinedTimeDomainFiltersPresetManager predefinedTimeDomainSampleFilterPresetManager; /** * Creates this panel and {@link #initialize() initializes} it. * @param predefinedTimeDomainSampleFilterPresetManager the manager at which * predefined {@link TimeDomainSampleFilter TimeDomainSampleFilters} are * stored */ public MontageFiltersPanel(PredefinedTimeDomainFiltersPresetManager predefinedTimeDomainSampleFilterPresetManager) { super(); this.predefinedTimeDomainSampleFilterPresetManager = predefinedTimeDomainSampleFilterPresetManager; initialize(); } /** * Initializes this panel with five subpanels: * <ul> * <li>the panel with the {@link #getFilteringEnabledCheckBox() check box} * to enable {@link Montage#isFiltered() signal filtering},</li> * <li>the panel with the {@link #getFiltersTable() table} with the list * of filters and two buttons: * <ul><li>the button to {@link #getEditFilterButton() edit} a filter,</li> * <li>the button to {@link #getRemoveFilterButton() remove} a filter,</li> * </ul></li> * <li>the panel which contains two buttons allowing to add a * {@link TimeDomainSampleFilter} to the list of filters: * <ul><li>the {@link #getAddTimeDomainFilterButton() button} and * {@link #getTimeDomainFilterTypeComboBox() combo-box} which adds the * predefined filter,</li> * <li>the {@link #getAddCustomTimeDomainFilterButton() button} which * opens a {@link #getEditTimeDomainSampleFilterDialog() dialog} to add * a custom filter,</li></ul></li> * <li>the panel which allows to add a {@link FFTSampleFilter} and contains * a {@link #getFftFilterTypeComboBox() combo-box} and a {@link * #getAddFFTFilterButton() button} do to it,</li> * <li>the panel with the {@link #getFilterExclusionTable() exclusion table}. * </li></ul> */ private void initialize() { addTimeDomainFilterAction = new AddTimeDomainFilterAction(); addCustomTimeDomainFilterAction = new AddCustomTimeDomainFilterAction(); addFFTFilterAction = new AddFFTFilterAction(); editFilterAction = new EditFilterAction(); removeFilterAction = new RemoveFilterAction(); selectAllFiltersAction = new SelectAllFiltersAction(); editFilterAction.setEnabled(false); removeFilterAction.setEnabled(false); setLayout(new GridLayout(1, 2, 3, 3)); JPanel masterSwitchPanel = createMasterSwitchPanel(); JPanel enableFiltfiltPanel = createEnableFiltfiltPanel(); JPanel filteringOptionsPanel = new JPanel(new BorderLayout(3, 3)); filteringOptionsPanel.add(masterSwitchPanel, BorderLayout.NORTH); filteringOptionsPanel.add(enableFiltfiltPanel, BorderLayout.SOUTH); //filters table panel JPanel filtersTablePanel = new JPanel(new BorderLayout(3, 3)); CompoundBorder border = new CompoundBorder( new TitledBorder(_("Filters")), new EmptyBorder(3, 3, 3, 3) ); filtersTablePanel.setBorder(border); JPanel filtersTableButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 3, 3)); filtersTableButtonPanel.add(getEditFilterButton()); filtersTableButtonPanel.add(getRemoveFilterButton()); filtersTablePanel.add(getFiltersScrollPane(), BorderLayout.CENTER); filtersTablePanel.add(filtersTableButtonPanel, BorderLayout.SOUTH); JPanel addTimeDomainFilterPanel = new JPanel(new BorderLayout(3, 3)); border = new CompoundBorder( new TitledBorder(_("Add time domain filter")), new EmptyBorder(3, 3, 3, 3) ); addTimeDomainFilterPanel.setBorder(border); SwingUtils.makeButtonsSameSize(new JButton[] {getAddTimeDomainFilterButton(), getAddFFTFilterButton(), getAddCustomTimeDomainFilterButton()}); addTimeDomainFilterPanel.add(getTimeDomainFilterTypeComboBox(), BorderLayout.CENTER); addTimeDomainFilterPanel.add(getAddTimeDomainFilterButton(), BorderLayout.EAST); JPanel addCustomTimeDomainFilterPanel = new JPanel(new BorderLayout(3, 3)); addTimeDomainFilterPanel.add(addCustomTimeDomainFilterPanel, BorderLayout.SOUTH); addCustomTimeDomainFilterPanel.add(getAddCustomTimeDomainFilterButton(), BorderLayout.EAST); JPanel addFftFilterPanel = new JPanel(new BorderLayout(3, 3)); border = new CompoundBorder( new TitledBorder(_("Add FFT filter")), new EmptyBorder(3, 3, 3, 3) ); addFftFilterPanel.setBorder(border); addFftFilterPanel.add(getFftFilterTypeComboBox(), BorderLayout.CENTER); addFftFilterPanel.add(getAddFFTFilterButton(), BorderLayout.EAST); JPanel bottomLeftPanel = new JPanel(new BorderLayout()); bottomLeftPanel.add(addTimeDomainFilterPanel, BorderLayout.CENTER); bottomLeftPanel.add(addFftFilterPanel, BorderLayout.SOUTH); JPanel leftPanel = new JPanel(new BorderLayout()); leftPanel.add(filteringOptionsPanel, BorderLayout.NORTH); leftPanel.add(filtersTablePanel, BorderLayout.CENTER); leftPanel.add(bottomLeftPanel, BorderLayout.SOUTH); JPanel rightButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 3, 3)); rightButtonPanel.add(getClearFilterExclusionButton()); JPanel rightPanel = new JPanel(new BorderLayout(3, 3)); border = new CompoundBorder( new TitledBorder(_("Filter enable table")), new EmptyBorder(3, 3, 3, 3) ); rightPanel.setBorder(border); rightPanel.add(getFilterExclusionScrollPane(), BorderLayout.CENTER); rightPanel.add(rightButtonPanel, BorderLayout.SOUTH); add(leftPanel); add(rightPanel); } /** * Creates and returns the panel containing the master switch (filters on/off). * @return the filters on/off panel */ private JPanel createMasterSwitchPanel() { JPanel masterSwitchPanel = new JPanel(new BorderLayout(3, 3)); CompoundBorder border = new CompoundBorder( new TitledBorder(_("Filtering master switch")), new EmptyBorder(3, 3, 3, 3)); masterSwitchPanel.setBorder(border); JLabel filteringEnabledLabel = new JLabel(_("Enable signal filtering")); masterSwitchPanel.add(filteringEnabledLabel, BorderLayout.CENTER); masterSwitchPanel.add(getFilteringEnabledCheckBox(), BorderLayout.EAST); return masterSwitchPanel; } /** * Creates and returns the panel containing the checkbox for enabling/disabling * filtfilt. * @return the panel with the filtfilt enable checkbox */ private JPanel createEnableFiltfiltPanel() { JPanel enableFiltfiltPanel = new JPanel(new BorderLayout(3, 3)); CompoundBorder border = new CompoundBorder( new TitledBorder(_("Filtfilt filtering switch")), new EmptyBorder(3, 3, 3, 3)); enableFiltfiltPanel.setBorder(border); JLabel filtfiltEnabledLabel = new JLabel(_("Enable filtfilt filtering (only for offline signals)")); enableFiltfiltPanel.add(filtfiltEnabledLabel, BorderLayout.CENTER); enableFiltfiltPanel.add(getFiltfiltEnabledCheckBox(), BorderLayout.EAST); return enableFiltfiltPanel; } /** * Gets the check box which states if the signal should be * {@link Montage#isFiltered() filtered}. * * @return the check box which states if the signal should be * {@link Montage#isFiltered() filtered} */ public JCheckBox getFilteringEnabledCheckBox() { if (filteringEnabledCheckBox == null) { filteringEnabledCheckBox = new JCheckBox(); filteringEnabledCheckBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (montage != null) { montage.setFilteringEnabled(getFilteringEnabledCheckBox().isSelected()); } } }); } return filteringEnabledCheckBox; } /** * Gets the check box which states if the signal should be * filtered using filtfilt algorithm * ({@link Montage#isFiltfiltEnabled()}. * * @return the check box which states if the signal should be * filtered using filtfilt algorithm */ public JCheckBox getFiltfiltEnabledCheckBox() { if (filtfiltEnabledCheckBox == null) { filtfiltEnabledCheckBox = new JCheckBox(); filtfiltEnabledCheckBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (montage != null) { montage.setFiltfiltEnabled(getFiltfiltEnabledCheckBox().isSelected()); } } }); } return filtfiltEnabledCheckBox; } /** * Gets the {@link MontageFiltersTableModel model} for the * {@link #filtersTable}. * * @return the {@link MontageFiltersTableModel model} for the * {@link #filtersTable} */ public MontageFiltersTableModel getFiltersTableModel() { if (filtersTableModel == null) { filtersTableModel = new MontageFiltersTableModel(); } return filtersTableModel; } /** * Gets the {@link MontageFiltersTable table} with the list of filters * associated with the {@link #getMontage() montage}. * * @return the {@link MontageFiltersTable table} with the list of filters * associated with the {@link #getMontage() montage} */ public MontageFiltersTable getFiltersTable() { if (filtersTable == null) { filtersTable = new MontageFiltersTable(getFiltersTableModel()); filtersTable.setPopupMenuProvider(new FiltersTablePopupProvider()); filtersTable.addMouseListener(new FiltersTableMouseHandler()); filtersTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { boolean enableActions = !(getFiltersTable().getSelectionModel().isSelectionEmpty()); editFilterAction.setEnabled(enableActions); removeFilterAction.setEnabled(enableActions); } }); } return filtersTable; } /** * Gets the scroll pane for the {@link #getFiltersTable() filters table}. * * @return the scroll pane for the {@link #getFiltersTable() filters table} */ public JScrollPane getFiltersScrollPane() { if (filtersScrollPane == null) { filtersScrollPane = new JScrollPane(getFiltersTable()); filtersScrollPane.setPreferredSize(new Dimension(200, 400)); } return filtersScrollPane; } /** * Gets the {@link MontageFilterEnableTableModel model} for the. * * @return the {@link MontageFilterEnableTableModel model} for the */ public MontageFilterEnableTableModel getFilterExclusionTableModel() { if (filterExclusionTableModel == null) { filterExclusionTableModel = new MontageFilterEnableTableModel(); } return filterExclusionTableModel; } /** * Gets the table which allows to select which {@link MontageChannel montage * channels} should not be {@link MontageSampleFilter filtered} by which * filter. * * @return the table which allows to select which {@link MontageChannel * montage channels} should not be {@link MontageSampleFilter * filtered} by which filter */ public MontageFilterEnableTable getFilterExclusionTable() { if (filterExclusionTable == null) { filterExclusionTable = new MontageFilterEnableTable(getFilterExclusionTableModel()); } return filterExclusionTable; } /** * Gets the scroll pane for the {@link #getFilterExclusionTable() filter * exclusion table}. * * @return the scroll pane for the {@link #getFilterExclusionTable() filter * exclusion table} */ public JScrollPane getFilterExclusionScrollPane() { if (filterExclusionScrollPane == null) { filterExclusionScrollPane = new JScrollPane(getFilterExclusionTable()); filterExclusionScrollPane.setPreferredSize(new Dimension(200, 400)); } return filterExclusionScrollPane; } /** * Returns the {@link ResolvableComboBox} allowing to select * a predefined {@link TimeDomainSampleFilter} to be added to the * signal chain. * @return the {@link ResolvableComboBox} to select a predefined filter */ public JComboBox getTimeDomainFilterTypeComboBox() { if (timeDomainFilterTypeComboBox == null) { timeDomainFilterTypeComboBox = new JComboBox(); timeDomainFilterTypeComboBox.setPreferredSize(new Dimension(200, 25)); } return timeDomainFilterTypeComboBox; } /** * Returns the {@link JComboBox} allowing to select whether the * * @return a {@link JComboBox} allowing to select initial parameters of the * {@link FFTSampleFilter} to be edited {@link FFTSampleFilter} * which will be shown in * {@link MontageFiltersPanel#editFFTSampleFilterDialog} will be * initially-passing or initially-stopping. */ public JComboBox getFftFilterTypeComboBox() { if (fftFilterTypeComboBox == null) { DefaultComboBoxModel model = new DefaultComboBoxModel(new Object[] { _("Initially passing filter"), _("Initially stopping filter") }); fftFilterTypeComboBox = new JComboBox(model); fftFilterTypeComboBox.setSelectedIndex(0); fftFilterTypeComboBox.setPreferredSize(new Dimension(200, 25)); } return fftFilterTypeComboBox; } /** * Returns a {@link JButton} allowing to add a predefined * * @return a button allowing to add a new predefined TimeDomainSampleFilter * to the signal chain {@link TimeDomainSampleFilter} to the signal * chain. */ public JButton getAddTimeDomainFilterButton() { if (addTimeDomainFilterButton == null) { addTimeDomainFilterButton = new JButton(addTimeDomainFilterAction); } return addTimeDomainFilterButton; } /** * Returns a button which opens a {@link EditTimeDomainSampleFilterDialog} * which allows to add a new custom designed * * @return a button allowing to open a * {@link EditTimeDomainSampleFilterDialog} * {@link TimeDomainSampleFilter} to the signal chain */ public JButton getAddCustomTimeDomainFilterButton() { if (addCustomTimeDomainFilterButton == null) { addCustomTimeDomainFilterButton = new JButton(addCustomTimeDomainFilterAction); } return addCustomTimeDomainFilterButton; } /** * Returns a button which opens a {@link EditFFTSampleFilterDialog} * which allows to add a new {@link FFTSampleFilter} to the signal chain. * @return a button allowing to open a {@link EditFFTSampleFilterDialog} */ public JButton getAddFFTFilterButton() { if (addFFTFilterButton == null) { addFFTFilterButton = new JButton(addFFTFilterAction); } return addFFTFilterButton; } /** * Gets the a button allowing to edit the selected filter's parameters. * * @return the a button allowing to edit the selected filter's parameters */ public JButton getEditFilterButton() { if (editFilterButton == null) { editFilterButton = new JButton(editFilterAction); } return editFilterButton; } /** * Gets the a button allowing to delete currently selected filter from the * list of filters. * * @return the a button allowing to delete currently selected filter from * the list of filters */ public JButton getRemoveFilterButton() { if (removeFilterButton == null) { removeFilterButton = new JButton(removeFilterAction); } return removeFilterButton; } /** * Gets the a button allowing to clear all selections in the. * * @return the a button allowing to clear all selections in the */ public JButton getClearFilterExclusionButton() { if (selectAllFiltersButton == null) { selectAllFiltersButton = new JButton(selectAllFiltersAction); } return selectAllFiltersButton; } /** * Gets the dialog that is used when editing. * * @return the dialog that is used when editing */ public EditFFTSampleFilterDialog getEditFFTSampleFilterDialog() { return editFFTSampleFilterDialog; } /** * Sets the dialog that is used when editing. * * @param editFFTSampleFilterDialog * the new dialog that is used when editing */ public void setEditFFTSampleFilterDialog(EditFFTSampleFilterDialog editFFTSampleFilterDialog) { this.editFFTSampleFilterDialog = editFFTSampleFilterDialog; } /** * Returns a {@link EditTimeDomainSampleFilterDialog} which can be opened * using this {@link MontageFiltersPanel}. * @return a {@link EditTimeDomainSampleFilterDialog} set for this panel */ public EditTimeDomainSampleFilterDialog getEditTimeDomainSampleFilterDialog() { return editTimeDomainSampleFilterDialog; } /** * Sets an {@link EditTimeDomainSampleFilterDialog} to be opened in this panel * when needed. * @param editTimeDomainSampleFilterDialog an EditTimeDomainSampleFilterDialog * to be opened in this panel */ public void setTimeDomainSampleFilterDialog(EditTimeDomainSampleFilterDialog editTimeDomainSampleFilterDialog) { this.editTimeDomainSampleFilterDialog = editTimeDomainSampleFilterDialog; } /** * Gets the {@link Montage montage} that is edited. * * @return the {@link Montage montage} that is edited */ public Montage getMontage() { return montage; } /** * Sets the {@link Montage montage} that is edited. * * @param montage * the new {@link Montage montage} that is edited */ public void setMontage(Montage montage) { if (this.montage != montage) { this.montage = montage; getFiltersTableModel().setMontage(montage); getFilterExclusionTableModel().setMontage(montage); if (montage != null) { updatePredefinedTimeDomainFiltersComboBox(); getFilteringEnabledCheckBox().setSelected(montage.isFilteringEnabled()); getFiltfiltEnabledCheckBox().setSelected(montage.isFiltfiltEnabled()); } else { getTimeDomainFilterTypeComboBox().setModel(new DefaultComboBoxModel(new Object[0])); getFilteringEnabledCheckBox().setSelected(false); getFiltfiltEnabledCheckBox().setSelected(false); } } } /** * Updates the combo box used for the selection of predefined filters * regarding the current sampling frequency. */ protected void updatePredefinedTimeDomainFiltersComboBox() { List<SampleFilterDefinition> predefinedFilters = predefinedTimeDomainSampleFilterPresetManager.getPredefinedFilters(getCurrentSamplingFrequency()); if (predefinedFilters == null) { //ErrorsDialog.showImmediateExceptionDialog(this, new ResolvableException("error.noPredefinedFiltersForThisSamplingFrequency")); logger.debug("No predefined filters for the current sampling frequency " + getCurrentSamplingFrequency()); getTimeDomainFilterTypeComboBox().setModel(new DefaultComboBoxModel(new Object[0])); return; } SampleFilterDefinition[] arr = new SampleFilterDefinition[predefinedFilters.size()]; predefinedFilters.toArray(arr); DefaultComboBoxModel model = new DefaultComboBoxModel(arr); JComboBox comboBox = getTimeDomainFilterTypeComboBox(); comboBox.setModel(model); if (model.getSize() > 0) comboBox.setSelectedIndex(0); comboBox.repaint(); } /** * Checks if is <code>true</code> if there exists a {@link SignalDocument * document} associated with the {@link Montage montage}, <code>false</code> * otherwise. * * @return the <code>true</code> if there exists a {@link SignalDocument * document} associated with the {@link Montage montage}, * <code>false</code> otherwise */ public boolean isSignalBound() { return signalBound; } /** * Sets the <code>true</code> if there exists a {@link SignalDocument * document} associated with the {@link Montage montage}, <code>false</code> * otherwise. * * @param signalBound * the new <code>true</code> if there exists a * {@link SignalDocument document} associated with the * {@link Montage montage}, <code>false</code> otherwise */ public void setSignalBound(boolean signalBound) { if (this.signalBound != signalBound) { this.signalBound = signalBound; } } /** * Gets the sampling frequency of the signal (the number of samples per * second). * * @return the sampling frequency of the signal (the number of samples per * second) */ public float getCurrentSamplingFrequency() { return currentSamplingFrequency; } /** * Sets the sampling frequency of the signal (the number of samples per * second). * * @param currentSamplingFrequency * the new sampling frequency of the signal (the number of * samples per second) */ public void setCurrentSamplingFrequency(float currentSamplingFrequency) { this.currentSamplingFrequency = currentSamplingFrequency; editFFTSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); editTimeDomainSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); updatePredefinedTimeDomainFiltersComboBox(); } /** * Action which creates a {@link TimeDomainSampleFilter} of a. * * {@link MontageFiltersPanel#getTimeDomainFilterTypeComboBox() selected} * type and adds it to the {@link MontageFiltersPanel#montage montage}. */ protected class AddTimeDomainFilterAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label, tooltip * and an icon for the button associated with this action. */ public AddTimeDomainFilterAction() { super(_("Add filter")); putValue(AbstractAction.SHORT_DESCRIPTION, _("Add selected time domain filter")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/addtimedomainfilter.png")); } /** * When the action is performed creates a {@link TimeDomainSampleFilter} * of a {@link MontageFiltersPanel#getTimeDomainFilterTypeComboBox() * selected} type and adds it to the {@link MontageFiltersPanel#montage * montage}. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } int index = getTimeDomainFilterTypeComboBox().getSelectedIndex(); TimeDomainSampleFilter filter = predefinedTimeDomainSampleFilterPresetManager.getPredefinedFilterAt(currentSamplingFrequency, index); if (filter == null) return; filter.setDescription(_("New time domain filter")); filter.setSamplingFrequency(currentSamplingFrequency); montage.addSampleFilter(filter); } } /** * Action which creates a {@link TimeDomainSampleFilter} and displays a. * * {@link MontageFiltersPanel#editTimeDomainSampleFilterDialog dialog} to * edit it. */ protected class AddCustomTimeDomainFilterAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label, tooltip * and an icon for the button associated with this action. */ public AddCustomTimeDomainFilterAction() { super(_("Add custom filter")); putValue(AbstractAction.SHORT_DESCRIPTION, _("Add a custom-made time domain filter")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/addcustomtimedomainfilter.png")); } /** * When the action is performed creates a {@link TimeDomainSampleFilter} * and displays a {@link * MontageFiltersPanel#editTimeDomainSampleFilterDialog dialog} to * edit it. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } TimeDomainSampleFilter filter = predefinedTimeDomainSampleFilterPresetManager.getCustomFilterStartingPoint(getCurrentSamplingFrequency()); if (filter == null) { filter = predefinedTimeDomainSampleFilterPresetManager.getCustomStartingPoint(); } filter.setDescription(_("New time domain filter")); filter.setSamplingFrequency(getCurrentSamplingFrequency()); editTimeDomainSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); boolean ok = editTimeDomainSampleFilterDialog.showDialog(filter, true); if (!ok) { return; } montage.addSampleFilter(filter); } } /** * Action which creates a {@link FFTSampleFilter} of a. * * {@link MontageFiltersPanel#getFftFilterTypeComboBox() selected} type and * adds it to the {@link MontageFiltersPanel#montage montage}. */ protected class AddFFTFilterAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label, tooltip * and an icon for the button associated with this action. */ public AddFFTFilterAction() { super(_("Add filter")); putValue(AbstractAction.SHORT_DESCRIPTION, _("Add new filter")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/addfftfilter.png")); } /** * When the action is performed creates a {@link FFTSampleFilter} of a * {@link MontageFiltersPanel#getFftFilterTypeComboBox() selected} * type and adds it to the {@link MontageFiltersPanel#montage montage}. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } int index = getFftFilterTypeComboBox().getSelectedIndex(); boolean initiallyPassing = (index == 0); FFTSampleFilter filter = new FFTSampleFilter(initiallyPassing); filter.setDescription(_("New FFT filter")); editFFTSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); boolean ok = editFFTSampleFilterDialog.showDialog(filter, true); if (!ok) { return; } montage.addSampleFilter(filter); } } /** * Action which displays the dialog to edit a selected * {@link MontageSampleFilter sample filter}: * <ul> * <li>{@link EditFFTSampleFilterDialog} if it is a. * * {@link FFTSampleFilter FFT filter},</li> * <li>{@link EditTimeDomainSampleFilterDialog} if it is a * {@link TimeDomainSampleFilter time domain filter}.</li> * </ul> */ protected class EditFilterAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label * and an icon for the button associated with this action. */ public EditFilterAction() { super(_("Edit filter")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/editfilter.png")); } /** * When the action is performed checks which {@link MontageSampleFilter * sample filter} in the {@link MontageFiltersPanel#getFiltersTable() * filters table} is selected and displays the dialog to edit it: * <ul> * <li>{@link EditFFTSampleFilterDialog} if it is a * {@link FFTSampleFilter FFT filter},</li> * <li>{@link EditTimeDomainSampleFilterDialog} if it is a * {@link TimeDomainSampleFilter time domain filter}.</li></ul> * After the dialog is closed with OK button updates the filter in * the {@link MontageFiltersPanel#montage montage}. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } int selectedRow = getFiltersTable().getSelectedRow(); if (selectedRow < 0) { return; } SampleFilterDefinition filter = montage.getSampleFilterAt(selectedRow); SampleFilterType type = filter.getType(); boolean ok; switch (type) { case TIME_DOMAIN : editTimeDomainSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); ok = editTimeDomainSampleFilterDialog.showDialog(filter, true); if (!ok) { return; } montage.updateSampleFilter(selectedRow, filter); break; case FFT : editFFTSampleFilterDialog.setCurrentSamplingFrequency(currentSamplingFrequency); ok = editFFTSampleFilterDialog.showDialog(filter, true); if (!ok) { return; } montage.updateSampleFilter(selectedRow, filter); break; default : throw new SanityCheckException("Unsupported filter type [" + type + "]"); } } } /** * Action which removes a selected {@link MontageSampleFilter sample * filter} from the {@link MontageFiltersPanel#montage montage}. */ protected class RemoveFilterAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label * and an icon for the button associated with this action. */ public RemoveFilterAction() { super(_("Remove filter")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/removefilter.png")); } /** * When this action is performed checks which {@link * MontageSampleFilter sample filter} in the * {@link MontageFiltersPanel#getFiltersTable() filters table} is * selected and {@link Montage#removeSampleFilter(int) removes} it from * the {@link MontageFiltersPanel#montage montage}. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } int selectedRow = getFiltersTable().getSelectedRow(); if (selectedRow < 0) { return; } montage.removeSampleFilter(selectedRow); } } /** * Action which removes all {@link Montage#clearFilterExclusion(int) * exclusions} of the channels from the {@link MontageSampleFilter * sample filters}. */ protected class SelectAllFiltersAction extends AbstractAction { /** the default serialization constant. */ private static final long serialVersionUID = 1L; /** * Constructor. Creates a new action and sets a label * and an icon for the button associated with this action. */ public SelectAllFiltersAction() { super(_("Enable all filters")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/selectall.png")); } /** * When this action is performed {@link * Montage#setFilterEnabled(int, boolean) enables} all {@link * MontageSampleFilter sample filters} and {@link * Montage#clearFilterExclusion(int) clears} their exclusions. * Also sets that no channel in the {@link Montage montage} * {@link Montage#setExcludeAllFilters(int, boolean) excludes all * filters}. */ @Override public void actionPerformed(ActionEvent ev) { if (montage == null) { return; } int count = montage.getSampleFilterCount(); int i; for (i = 0; i < count; i++) { montage.setFilterEnabled(i, true); montage.clearFilterExclusion(i); } count = montage.getMontageChannelCount(); for (i = 0; i < count; i++) { montage.setExcludeAllFilters(i, false); } } } /** * Provider of popup menus with two buttons: * <ul> * <li>button to {@link EditFilterAction edit} a filter,</li> * <li>button to {@link RemoveFilterAction remove} a filter.</li></ul> */ protected class FiltersTablePopupProvider implements TablePopupMenuProvider { /** * a popup menu with two buttons: * <ul> * <li>button to {@link EditFilterAction edit} a filter,</li> * <li>button to {@link RemoveFilterAction remove} a filter</li> * </ul> * . */ private JPopupMenu popupMenu; /** * Returns a {@link #getDefaultPopupMenu() default popup menu}. */ @Override public JPopupMenu getPopupMenu(int col, int row) { return getDefaultPopupMenu(); } /** * Returns a {@link #getDefaultPopupMenu() default popup menu}. * * @return the a popup menu with two buttons: * <ul> * <li>button to {@link EditFilterAction edit} a filter,</li> * <li>button to {@link RemoveFilterAction remove} a filter</li> * </ul> */ @Override public JPopupMenu getPopupMenu() { return getPopupMenu(-1,-1); } /** * Provides a popup menu with two buttons: * <ul> * <li>button to {@link EditFilterAction edit} a filter,</li> * <li>button to {@link RemoveFilterAction remove} a filter.</li></ul> * @return a popup menu with two buttons: * <ul> * <li>button to {@link EditFilterAction edit} a filter,</li> * <li>button to {@link RemoveFilterAction remove} a filter.</li></ul> */ private JPopupMenu getDefaultPopupMenu() { if (popupMenu == null) { popupMenu = new JPopupMenu(); popupMenu.add(editFilterAction); popupMenu.addSeparator(); popupMenu.add(removeFilterAction); } return popupMenu; } } /** * Mouse handler which {@link EditFilterAction edits} a filter * when it is double clicked. */ protected class FiltersTableMouseHandler extends MouseAdapter { /** * When the double click with the left mouse button occurs {@link * EditFilterAction} is performed. */ @Override public void mouseClicked(MouseEvent e) { MontageFiltersTable table = (MontageFiltersTable) e.getSource(); if (SwingUtilities.isLeftMouseButton(e) && (e.getClickCount() % 2) == 0) { int selRow = table.rowAtPoint(e.getPoint()); if (selRow >= 0) { editFilterAction.actionPerformed(new ActionEvent(table, 0, "edit")); } } } } }