/* ChannelSpacePanel.java created 2008-01-25 * */ package org.signalml.app.view.signal.signalselection; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import org.apache.log4j.Logger; import org.signalml.app.action.util.ListSelectAllAction; import org.signalml.app.action.util.ListSelectInvertAction; import org.signalml.app.action.util.ListSelectNoneAction; import org.signalml.app.model.components.validation.ValidationErrors; import org.signalml.domain.signal.space.ChannelSpace; import org.signalml.domain.signal.space.ChannelSpaceType; import org.signalml.domain.signal.space.SignalSourceLevel; import org.signalml.domain.signal.space.SignalSpace; import org.signalml.domain.signal.space.SignalSpaceConstraints; /** * Panel which allows to select channels from the {@link #getChannelList() list} * containing their names (labels). Contains two sub-panels: * <ul> * <li>the {@link #getChannelScrollPane() pane} with the list of channels,</li> * <li>the panel with 3 buttons (from top to bottom): * <ul> * <li>to select {@link #getChannelSelectAllButton() all} channel,</li> * <li>to select {@link #getChannelSelectNoneButton() no} channels,</li> * <li>to {@link #getChannelSelectInvertButton() invert} the selection of * channels.</li> * </ul> * </li> * </ul> * Channels can be selected from the list of {@link #getSourceChannels()}. * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe * Sp. z o.o. */ public class ChannelSpacePanel extends JPanel { private static final long serialVersionUID = 1L; protected static final Logger logger = Logger.getLogger(ChannelSpacePanel.class); /** * the list with the names of channels; multiple selection is allowed */ private JList channelList; /** * the scroll pane with the {@link #channelList list} of names of channels */ private JScrollPane channelScrollPane; /** * the button which selects all channels on the {@link #channelList list} */ private JButton channelSelectAllButton; /** * the button which inverts the selection on the {@link #channelList list} */ private JButton channelSelectInvertButton; /** * the button which makes there is no element selected on the * {@link #channelList list} */ private JButton channelSelectNoneButton; /** * the currently selected {@link SignalSourceLevel level} of signal * processing */ private SignalSourceLevel currentLevel; /** * the list of names (labels) of channels of the currently * {@link #currentLevel selected} {@link SignalSourceLevel level} */ private String[] currentChannels; /** * the array of names (labels) of source channels */ private String[] sourceChannels; /** * the array of names (labels) of all montage channels available */ private String[] channels; /** * Constructor. Initializes the panel. */ public ChannelSpacePanel() { super(); initialize(); } /** * Initializes this panel with BorderLayout and two sub-panels: * <ul> * <li>the {@link #getChannelScrollPane() pane} with the list of channels,</li> * <li>the panel with 3 buttons (from top to bottom): * <ul> * <li>to select {@link #getChannelSelectAllButton() all} channel,</li> * <li>to select {@link #getChannelSelectNoneButton() no} channels,</li> * <li>to {@link #getChannelSelectInvertButton() invert} the selection of * channels.</li> * </ul> * </li> * </ul> */ private void initialize() { setLayout(new BorderLayout()); setBorder(new CompoundBorder(new TitledBorder(_("Channel selection")), new EmptyBorder(3, 3, 3, 3))); JPanel channelButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 3, 3)); channelButtonPanel.add(getChannelSelectAllButton()); channelButtonPanel.add(getChannelSelectNoneButton()); channelButtonPanel.add(getChannelSelectInvertButton()); add(getChannelScrollPane(), BorderLayout.CENTER); add(channelButtonPanel, BorderLayout.SOUTH); } /** * Returns the list with the names (labels) of channels. If the list doesn't * exist it is created with multiple selection allowed. * * @return the list with the names (labels) of channels */ public JList getChannelList() { if (channelList == null) { channelList = new JList(); channelList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); } return channelList; } /** * Returns the pane with the {@link #getChannelList() list} of the names * (labels) of channels. If the pane doesn't exist it is created. * * @return the pane with the list of the names of channels */ public JScrollPane getChannelScrollPane() { if (channelScrollPane == null) { channelScrollPane = new JScrollPane(getChannelList()); channelScrollPane.setPreferredSize(new Dimension(300, 200)); } return channelScrollPane; } /** * Returns the button which selects all channels on the * {@link #getChannelList() list}. If the button doesn't exist it is * created. * * @return the button which selects all channels on the list */ public JButton getChannelSelectAllButton() { if (channelSelectAllButton == null) { channelSelectAllButton = new JButton(new ListSelectAllAction(getChannelList())); } return channelSelectAllButton; } /** * Returns the button which makes there is no element selected on the * {@link #getChannelList() list}. If the button doesn't exist it is * created. * * @return the button which makes there is no element selected on the list */ public JButton getChannelSelectNoneButton() { if (channelSelectNoneButton == null) { channelSelectNoneButton = new JButton(new ListSelectNoneAction(getChannelList())); } return channelSelectNoneButton; } /** * Returns the button which inverts the selection on the * {@link #getChannelList() list}. If the button doesn't exist it is * created. * * @return the button which inverts the selection on the list */ public JButton getChannelSelectInvertButton() { if (channelSelectInvertButton == null) { channelSelectInvertButton = new JButton(new ListSelectInvertAction(getChannelList())); } return channelSelectInvertButton; } /** * Using the {@link ChannelSpace} from given {@link SignalSpace model} sets * which elements on the {@link #getChannelList() list} are selected. * * @param space * the signal space */ public void fillPanelFromModel(SignalSpace space) { ChannelSpaceType channelSpaceType = space.getChannelSpaceType(); JList list = getChannelList(); if (channelSpaceType == ChannelSpaceType.WHOLE_SIGNAL) { list.setSelectionInterval(0, list.getModel().getSize() - 1); } else { ChannelSpace channelSpace = space.getChannelSpace(); list.clearSelection(); if (channels != null && channelSpace != null) { for (int i = 0; i < channels.length; i++) { if (channelSpace.isChannelSelected(i)) { list.addSelectionInterval(i, i); } } } } } /** * Stores the information which channels on the {@link #getChannelList() * list} are selected in the {@link SignalSpace model}. In order to do it: * <ul> * <li>if all channels are selected * {@link SignalSpace#setChannelSpaceType(ChannelSpaceType) sets} the * {@link ChannelSpaceType type} of {@link ChannelSpace} in the model,</li> * <li>otherwise stores this information in channel space and sets in the * model,</li> * </ul> * * @param space * the signal space */ public void fillModelFromPanel(SignalSpace space) { boolean all = true; JList list = getChannelList(); ChannelSpace channelSpace = space.getChannelSpace(); if (channelSpace != null) { channelSpace.clear(); } else { channelSpace = new ChannelSpace(); } if (channels != null) { for (int i = 0; i < channels.length; i++) { if (list.isSelectedIndex(i)) { channelSpace.addChannel(i); } else { all = false; } } } if (all) { space.setChannelSpaceType(ChannelSpaceType.WHOLE_SIGNAL); space.setChannelSpace(null); } else { space.setChannelSpaceType(ChannelSpaceType.SELECTED); space.setChannelSpace(channelSpace); } } /** * Returns the array of names (labels) of montage channels. * * @return the array of names (labels) of montage channels */ public String[] getChannels() { return channels; } /** * Sets the array of names (labels) of montage channels. * * @param channels * the array of names (labels) of montage channels */ public void setChannels(String[] channels) { if (this.channels != channels) { this.channels = channels; if (currentLevel != SignalSourceLevel.RAW) { setCurrentChannels(channels); } } } /** * Returns the currently selected {@link SignalSourceLevel level} of signal * processing. * * @return the currently selected level of signal processing */ public SignalSourceLevel getCurrentLevel() { return currentLevel; } /** * Sets the currently selected {@link SignalSourceLevel level} of signal * processing. According to this level sets appropriate channels as * {@link #setCurrentChannels(String[]) current channels}. * * @param currentLevel * the currently selected level of signal processing */ public void setCurrentLevel(SignalSourceLevel currentLevel) { if (this.currentLevel != currentLevel) { this.currentLevel = currentLevel; if (currentLevel == SignalSourceLevel.RAW) { setCurrentChannels(sourceChannels); } else { setCurrentChannels(channels); } } } /** * Returns the array of names (labels) of source channels. * * @return the array of names (labels) of source channels */ public String[] getSourceChannels() { return sourceChannels; } /** * Sets the array of names (labels) of source channels. If the * {@link #getCurrentLevel() current level} is RAW, sets this channels as * {@link #setCurrentChannels(String[]) current channels}. * * @param sourceChannels * the array of names (labels) of source channels */ public void setSourceChannels(String[] sourceChannels) { if (this.sourceChannels != sourceChannels) { this.sourceChannels = sourceChannels; if (currentLevel == SignalSourceLevel.RAW) { setCurrentChannels(sourceChannels); } } } /** * Returns the list of names (labels) of channels of the currently * {@link #getCurrentLevel() selected} {@link SignalSourceLevel level}. * * @return the list of names (labels) of channels of the currently selected * level */ public String[] getCurrentChannels() { return currentChannels; } /** * Sets the list of names (labels) of channels of the currently * {@link #getCurrentLevel() selected} {@link SignalSourceLevel level}. This * list is encapsulated in the model and set as the model to * {@link #getChannelList() channel list}. * * @param currentChannels * the list of names (labels) of channels of the currently * selected level */ public void setCurrentChannels(String[] currentChannels) { if (this.currentChannels != currentChannels) { this.currentChannels = currentChannels; DefaultListModel listModel = new DefaultListModel(); for (int i = 0; i < currentChannels.length; i++) { listModel.addElement(currentChannels[i]); } JList list = getChannelList(); list.setModel(listModel); list.clearSelection(); } } /** * Sets the names of {@link #setSourceChannels(String[]) source} and * {@link #setChannels(String[]) montage} channels using the given * {@link SignalSpaceConstraints parameters} of the signal. * * @param constraints * the parameters of the signal */ public void setConstraints(SignalSpaceConstraints constraints) { setChannels(constraints.getChannels()); setSourceChannels(constraints.getSourceChannels()); } /** * Validates this panel. This panel is valid if there is at least one * channel selected. * * @param errors * the object in which errors are stored */ public void validatePanel(ValidationErrors errors) { if (getChannelList().isSelectionEmpty()) { errors.addError(_("At least one channel must be selected")); } } }