/* EditMontagePanel.java created 2007-10-24 * */ package org.signalml.app.view.montage; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Window; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; 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.document.signal.SignalDocument; import org.signalml.app.model.montage.MontageTableModel; import org.signalml.app.model.montage.SourceMontageTableModel; import org.signalml.app.util.IconUtils; import org.signalml.app.util.SwingUtils; import org.signalml.app.view.TablePopupMenuProvider; import org.signalml.app.view.common.dialogs.errors.Dialogs; import org.signalml.app.view.montage.dnd.MontageWasteBasket; import org.signalml.app.view.montage.dnd.MontageWasteBasketTransferHandler; import org.signalml.domain.montage.Montage; import org.signalml.domain.montage.MontageChannel; import org.signalml.domain.montage.MontageException; import org.signalml.domain.montage.SourceChannel; import org.signalml.domain.montage.system.ChannelFunction; import org.signalml.domain.montage.system.IChannelFunction; /** * The panel which allows to: * <ul> * <li>select which {@link SourceChannel source channels} should be included * in the Montage,</li> * <li>change the label of both source and {@link MontageChannel montage} * channels,</li> * <li>change the order of montage channels.</li> * </ul> * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class MontageChannelsPanel extends JPanel { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * the logger */ protected static final Logger logger = Logger.getLogger(MontageChannelsPanel.class); /** * the {@link Montage montage} that is the model for this panel */ private Montage montage; /** * {@code true} if the {@link SignalDocument signal document} exists * {@code false} otherwise */ private boolean signalBound; /** * the {@link SourceMontageTableModel model} for * {@link #getSourceMontageTable()} */ private SourceMontageTableModel sourceMontageTableModel; /** * the {@link MontageTableModel model} for {@link #montageTable} */ private MontageTableModel montageTableModel; /** * the {@link SourceMontageTable table} which allows to edit the labels and * functions of {@link SourceChannel source channels} */ private SourceMontageTable sourceMontageTable; /** * the {@link MontageTable table} which allows to edit the labels and * the order (the indexes) of {@link MontageChannel montage channels} */ private MontageTable montageTable; /** * the scroll pane with the {@link #getSourceMontageTable() source montage * table} */ private JScrollPane sourceScrollPane; /** * the scroll pane with the {@link #getMontageTable() montage table} */ private JScrollPane scrollPane; /** * the panel with the {@link SourceMontageTable} enclosed in the * {@link #getSourceScrollPane() scroll pane} and the panel * with two buttons ({@link #addSourceChannelButton} and * {@link #removeSourceChannelButton}) below the table */ private JPanel sourceTablePanel; /** * the panel with the {@link MontageTable} enclosed in the * {@link #getScrollPane() scroll pane} and the panel * with one button ({@link #clearMontageButton}) below the table */ private JPanel montageTablePanel; /** * the {@link MoveUpAction action} which moves the selected * {@link MontageChannel montage channel} up in the * {@link #getMontageTable() montage table} (changes its index from * {@code i} to {@code i - 1} and changes the index of the above channel * from {@code i - 1} to {@code i}) */ private Action moveUpAction; /** * the {@link MoveDownAction action} which moves the selected * {@link MontageChannel montage channel} down in the * {@link #getMontageTable() montage table} (changes its index * from {@code i} to {@code i + 1} and changes the index of the * channel below from {@code i + 1} to {@code i}) */ private Action moveDownAction; /** * the {@link AddChannelsAction action} which adds the selected * {@link SourceChannel source channel} to the target {@link Montage * montage} */ private Action addChannelsAction; /** * the {@link RemoveChannelsAction action} which removes the selected * {@link MontageChannel montage channel} from the {@link Montage * montage} */ private Action removeChannelsAction; private Action addZeroChannelAction; private Action addOneChannelAction; /** * the {@link RemoveSourceChannelAction action} which * {@link Montage#removeSourceChannel() removes} the {@link SourceChannel * source channel} from the {@link Montage montage} */ private Action removeSourceChannelAction; /** * the {@link ClearMontageAction action} which {@link Montage#reset() * removes} all {@link MontageChannel montage channels} from the * {@link Montage montage} */ private Action clearMontageAction; /** * the button for the {@link #moveUpAction} */ private JButton moveUpButton; /** * the button for the {@link #moveDownAction} */ private JButton moveDownButton; /** * the button for the {@link #addChannelsAction} */ private JButton addChannelsButton; /** * the button for the {@link #removeChannelsAction} */ private JButton removeChannelsButton; private JButton addZeroChannelButton; private JButton addOneChannelButton; /** * the button for the {@link #removeSourceChannelAction} */ private JButton removeSourceChannelButton; /** * the button for the {@link #clearMontageAction} */ private JButton clearMontageButton; /** * Constructor. Sets the source of messages and {@link #initialize() * initializes} this panel. */ public MontageChannelsPanel() { super(); initialize(); } /** * Initializes this panel: * <ul> * <li>creates all actions and assigns them to buttons,</li> * <li>creates the center panel with buttons - {@link #moveUpButton}, * {@link #moveDownButton}, {@link #addChannelsButton} and * {@link #removeChannelsButton} - and the waste basked,</li> * <li>adds subpanels to this panel (from left to right): * <ul> * <li>the {@link #sourceTablePanel panel} with the * {@link SourceMontageTable},</li> * <li>the center panel as described above,</li> * <li>the {@link #montageTablePanel panel} with the * {@link MontageTable}.</li></ul></li></ul> */ private void initialize() { setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); moveUpAction = new MoveUpAction(); moveDownAction = new MoveDownAction(); addChannelsAction = new AddChannelsAction(); removeChannelsAction = new RemoveChannelsAction(); addZeroChannelAction = new AddSourceChannelAction(0, _("ZEROs channel")); addOneChannelAction = new AddSourceChannelAction(1, _("ONEs channel")); removeSourceChannelAction = new RemoveSourceChannelAction(); clearMontageAction = new ClearMontageAction(); moveUpButton = new JButton(moveUpAction); moveUpButton.setHorizontalAlignment(SwingConstants.LEFT); moveDownButton = new JButton(moveDownAction); moveDownButton.setHorizontalAlignment(SwingConstants.LEFT); addChannelsButton = new JButton(addChannelsAction); addChannelsButton.setHorizontalAlignment(SwingConstants.LEFT); removeChannelsButton = new JButton(removeChannelsAction); removeChannelsButton.setHorizontalAlignment(SwingConstants.LEFT); SwingUtils.makeButtonsSameSize(new JButton[] { moveUpButton, moveDownButton, addChannelsButton, removeChannelsButton }); addZeroChannelButton = new JButton(addZeroChannelAction); addOneChannelButton = new JButton(addOneChannelAction); removeSourceChannelButton = new JButton(removeSourceChannelAction); clearMontageButton = new JButton(clearMontageAction); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); buttonPanel.setBorder(new EmptyBorder(getSourceTablePanel().getInsets().top,3,0,3)); buttonPanel.add(moveUpButton); buttonPanel.add(Box.createVerticalStrut(3)); buttonPanel.add(moveDownButton); buttonPanel.add(Box.createVerticalStrut(6)); buttonPanel.add(addChannelsButton); buttonPanel.add(Box.createVerticalStrut(3)); buttonPanel.add(removeChannelsButton); buttonPanel.add(Box.createVerticalStrut(6)); buttonPanel.add(Box.createVerticalGlue()); MontageWasteBasket montageWasteBasket = new MontageWasteBasket(); MontageWasteBasketTransferHandler montageWasteBasketTransferHandler = new MontageWasteBasketTransferHandler(getMontageTable()); montageWasteBasket.setTransferHandler(montageWasteBasketTransferHandler); montageWasteBasket.setAlignmentX(Component.CENTER_ALIGNMENT); montageWasteBasket.setToolTipText(_("Drop target channels here to delete them")); JPanel centerPanel = new JPanel(new BorderLayout()); centerPanel.add(buttonPanel, BorderLayout.CENTER); centerPanel.add(montageWasteBasket, BorderLayout.SOUTH); add(getSourceTablePanel()); add(centerPanel); add(getMontageTablePanel()); } /** * Enables or disables buttons (actions). The buttons are enabled if: * <ul> * <li>{@link #addChannelsButton} - if there are some selected rows in * {@link #getSourceMontageTable() source montage table},</li> * <li>{@link #removeChannelsButton} - if there are some selected rows in * {@link #getMontageTable() montage table},</li> * <li>{@link #moveUpButton} and {@link #moveDownButton} - if the selection * in the montage table is continuous.</li> * </ul> */ private void setEnableds() { boolean sourceSelection = !getSourceMontageTable().getSelectionModel().isSelectionEmpty(); boolean montageSelection = !getMontageTable().getSelectionModel().isSelectionEmpty(); boolean montageSelectionContiguous = false; if (montageSelection) { montageSelectionContiguous = true; ListSelectionModel selectionModel = getMontageTable().getSelectionModel(); int firstRow = selectionModel.getMinSelectionIndex(); int lastRow = selectionModel.getMaxSelectionIndex(); for (int i=firstRow+1; i<lastRow; i++) { if (!selectionModel.isSelectedIndex(i)) { montageSelectionContiguous = false; break; } } } moveUpAction.setEnabled(montageSelectionContiguous); moveDownAction.setEnabled(montageSelectionContiguous); addChannelsAction.setEnabled(sourceSelection); removeChannelsAction.setEnabled(montageSelection); } /** * Gets the panel with the {@link SourceMontageTable} enclosed in the. * * @return the panel with the {@link SourceMontageTable} enclosed in the */ public JPanel getSourceTablePanel() { if (sourceTablePanel == null) { sourceTablePanel = new JPanel(new BorderLayout()); CompoundBorder border = new CompoundBorder( new TitledBorder(_("Source montage")), new EmptyBorder(3,3,3,3) ); sourceTablePanel.setBorder(border); JPanel sourceButtonPanel = new JPanel(); sourceButtonPanel.setLayout(new BoxLayout(sourceButtonPanel, BoxLayout.X_AXIS)); sourceButtonPanel.setBorder(new EmptyBorder(5,0,0,0)); sourceButtonPanel.add(addZeroChannelButton); sourceButtonPanel.add(Box.createHorizontalStrut(5)); sourceButtonPanel.add(addOneChannelButton); sourceButtonPanel.add(Box.createHorizontalStrut(5)); sourceButtonPanel.add(removeSourceChannelButton); sourceButtonPanel.add(Box.createHorizontalGlue()); sourceTablePanel.add(getSourceScrollPane(), BorderLayout.CENTER); sourceTablePanel.add(sourceButtonPanel, BorderLayout.SOUTH); } return sourceTablePanel; } /** * Gets the panel with the {@link MontageTable} enclosed in the. * * @return the panel with the {@link MontageTable} enclosed in the */ public JPanel getMontageTablePanel() { if (montageTablePanel == null) { montageTablePanel = new JPanel(); montageTablePanel.setLayout(new BorderLayout()); CompoundBorder border = new CompoundBorder( new TitledBorder(_("Target montage")), new EmptyBorder(3,3,3,3) ); montageTablePanel.setBorder(border); JPanel montageButtonPanel = new JPanel(); montageButtonPanel.setLayout(new BoxLayout(montageButtonPanel, BoxLayout.X_AXIS)); montageButtonPanel.setBorder(new EmptyBorder(5,0,0,0)); montageButtonPanel.add(Box.createHorizontalGlue()); montageButtonPanel.add(clearMontageButton); montageTablePanel.add(getScrollPane(), BorderLayout.CENTER); montageTablePanel.add(montageButtonPanel, BorderLayout.SOUTH); } return montageTablePanel; } /** * Gets the {@link SourceMontageTableModel model} for. * * @return the {@link SourceMontageTableModel model} for */ public SourceMontageTableModel getSourceMontageTableModel() { if (sourceMontageTableModel == null) { sourceMontageTableModel = new SourceMontageTableModel(); } return sourceMontageTableModel; } /** * Gets the {@link MontageTableModel model} for {@link #montageTable}. * * @return the {@link MontageTableModel model} for {@link #montageTable} */ public MontageTableModel getMontageTableModel() { if (montageTableModel == null) { montageTableModel = new MontageTableModel(); } return montageTableModel; } /** * Gets the {@link MontageTable table} which allows to edit the labels and * the order (the indexes) of {@link MontageChannel montage channels}. * * @return the {@link MontageTable table} which allows to edit the labels * and the order (the indexes) of {@link MontageChannel montage * channels} */ public MontageTable getMontageTable() { if (montageTable == null) { montageTable = new MontageTable(getMontageTableModel(), false); montageTable.setPopupMenuProvider(new MontageTablePopupProvider()); montageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (!getMontageTable().getSelectionModel().isSelectionEmpty()) { getSourceMontageTable().clearSelection(); } setEnableds(); } }); } return montageTable; } /** * Gets the {@link SourceMontageTable table} which allows to edit the labels * and functions of {@link SourceChannel source channels}. * * @return the {@link SourceMontageTable table} which allows to edit the * labels and functions of {@link SourceChannel source channels} */ public SourceMontageTable getSourceMontageTable() { if (sourceMontageTable == null) { sourceMontageTable = new SourceMontageTable(getSourceMontageTableModel()); sourceMontageTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); sourceMontageTable.setPopupMenuProvider(new SourceMontageTablePopupProvider()); sourceMontageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (!getSourceMontageTable().getSelectionModel().isSelectionEmpty()) { getMontageTable().clearSelection(); } setEnableds(); } }); } return sourceMontageTable; } /** * Gets the scroll pane with the {@link #getMontageTable() montage table}. * * @return the scroll pane with the {@link #getMontageTable() montage table} */ public JScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new JScrollPane(getMontageTable()); } return scrollPane; } /** * Gets the scroll pane with the {@link #getSourceMontageTable() source * montage table}. * * @return the scroll pane with the {@link #getSourceMontageTable() source * montage table} */ public JScrollPane getSourceScrollPane() { if (sourceScrollPane == null) { sourceScrollPane = new JScrollPane(getSourceMontageTable()); } return sourceScrollPane; } /** * Gets the {@link Montage montage} that is the model for this panel. * * @return the {@link Montage montage} that is the model for this panel */ public Montage getMontage() { return montage; } /** * Sets the {@link Montage montage} that is the model for this panel. * * @param montage * the new {@link Montage montage} that is the model for this * panel */ public void setMontage(Montage montage) { if (this.montage != montage) { this.montage = montage; getSourceMontageTableModel().setMontage(montage); getMontageTableModel().setMontage(montage); getSourceMontageTable().clearSelection(); getMontageTable().clearSelection(); setEnableds(); } } /** * Checks if is signal bound. * * @return true, if is signal bound */ public boolean isSignalBound() { return signalBound; } /** * Sets the signal bound. * * @param signalBound * the new signal bound */ public void setSignalBound(boolean signalBound) { if (this.signalBound != signalBound) { this.signalBound = signalBound; } } /** * The action which that which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#moveMontageChannelRange(int, int, int) * moves} them one position backward. */ protected class MoveUpAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public MoveUpAction() { super(_("Move up")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/moveup.png")); } /** * When the action is performed checks which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#moveMontageChannelRange(int, int, int) * moves} them one position backward. */ @Override public void actionPerformed(ActionEvent ev) { ListSelectionModel selectionModel = getMontageTable().getSelectionModel(); int firstRow = selectionModel.getMinSelectionIndex(); if (firstRow <= 0) { return; } int lastRow = selectionModel.getMaxSelectionIndex(); for (int i=firstRow+1; i<lastRow; i++) { if (!selectionModel.isSelectedIndex(i)) { // non-contiguous return; } } montage.moveMontageChannelRange(firstRow, 1+lastRow-firstRow, -1); selectionModel.setSelectionInterval(firstRow-1, lastRow-1); } } /** * The action which that which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#moveMontageChannelRange(int, int, int) * moves} them one position forward. */ protected class MoveDownAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public MoveDownAction() { super(_("Move down")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/movedown.png")); } /** * When the action is performed checks which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#moveMontageChannelRange(int, int, int) * moves} them one position forward. */ @Override public void actionPerformed(ActionEvent ev) { ListSelectionModel selectionModel = getMontageTable().getSelectionModel(); int firstRow = selectionModel.getMinSelectionIndex(); if (firstRow < 0) { return; } int lastRow = selectionModel.getMaxSelectionIndex(); if (lastRow >= getMontageTable().getRowCount()-1) { return; } for (int i=firstRow+1; i<lastRow; i++) { if (!selectionModel.isSelectedIndex(i)) { // non-contiguous return; } } montage.moveMontageChannelRange(firstRow, 1+lastRow-firstRow, 1); selectionModel.setSelectionInterval(firstRow+1, lastRow+1); } } /** * Action that checks which rows in the * {@link MontageChannelsPanel#getSourceMontageTable() source montage * table} are selected and {@link Montage#addMontageChannels(int[], int) * adds} the new {@link MontageChannel montage channels} (created on * the basis of the {@link SourceChannel source channels} of the * selected indexes) to the {@link Montage montage}. */ protected class AddChannelsAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public AddChannelsAction() { super(_("Add channels")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/addchannels.png")); } /** * When the action is performed checks which rows in the * {@link MontageChannelsPanel#getSourceMontageTable() source montage * table} are selected and {@link Montage#addMontageChannels(int[], int) * adds} the new {@link MontageChannel montage channels} (created on * the basis of the {@link SourceChannel source channels} of the * selected indexes) to the {@link Montage montage}. */ @Override public void actionPerformed(ActionEvent ev) { ListSelectionModel selectionModel = getSourceMontageTable().getSelectionModel(); int firstRow = selectionModel.getMinSelectionIndex(); if (firstRow < 0) { return; } int lastRow = selectionModel.getMaxSelectionIndex(); int[] selection = new int[getSourceMontageTable().getRowCount()]; int cnt = 0; for (int i=firstRow; i<=lastRow; i++) { if (selectionModel.isSelectedIndex(i)) { selection[cnt] = i; cnt++; } } selection = Arrays.copyOf(selection, cnt); montage.addMontageChannels(selection); } } /** * Action that checks which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#removeMontageChannels(int[]) * removes} them from the {@link Montage montage}. */ protected class RemoveChannelsAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public RemoveChannelsAction() { super(_("Remove channels")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/removechannels.png")); } /** * When the action is performed checks which rows in the * {@link MontageChannelsPanel#getMontageTable() montage table} are * selected and {@link Montage#removeMontageChannels(int[]) * removes} them from the {@link Montage montage}. */ @Override public void actionPerformed(ActionEvent ev) { ListSelectionModel selectionModel = getMontageTable().getSelectionModel(); int firstRow = selectionModel.getMinSelectionIndex(); if (firstRow < 0) { return; } int lastRow = selectionModel.getMaxSelectionIndex(); int[] selection = new int[getMontageTable().getRowCount()]; int cnt = 0; for (int i=firstRow; i<=lastRow; i++) { if (selectionModel.isSelectedIndex(i)) { selection[cnt] = i; cnt++; } } selection = Arrays.copyOf(selection, cnt); montage.removeMontageChannels(selection); } } /** * Action which:<ul> * <li>if the document with the signal exists does nothing,</li> * <li>otherwise * {@link Montage#addSourceChannel(String, org.signalml.domain.montage.Channel) * adds} a new {@link SourceChannel source channel} to the {@link Montage * montage}.</li> * </ul> */ protected class AddSourceChannelAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; private int channelType; /** * Constructor. Sets the text and the icon of this button. */ public AddSourceChannelAction(int t, String msg) { super(msg); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/addsourcechannel.png")); this.channelType = t; } /** * When the action is performed: * <ul> * <li>if the document with the signal exists does nothing,</li> * <li>otherwise * {@link Montage#addSourceChannel(String, org.signalml.domain.montage.Channel) * adds} a new {@link SourceChannel source channel} to the {@link Montage * montage}.</li> * </ul> */ @Override public void actionPerformed(ActionEvent ev) { /*if (signalBound) { return; }*/ try { if (this.channelType == 0) { String lb = montage.getNewSourceChannelLabel(_("ZERO")); montage.addSourceChannel(lb, ChannelFunction.ZERO); } else {//assumed ONE String lb = montage.getNewSourceChannelLabel(_("ONE")); montage.addSourceChannel(lb, ChannelFunction.ONE); } } catch (MontageException ex) { logger.error("Failed to add source channel", ex); Dialogs.showExceptionDialog((Window) null, ex); return; } } } /** * Action for removing a source montage from channel. If this action cannot * be performed an error dialog is shown. */ protected class RemoveSourceChannelAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public RemoveSourceChannelAction() { super(_("Remove")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/removesourcechannel.png")); } /** * If the last channel in source montage is a {@link ChannelFunction#ZERO} * or a {@link ChannelFunction#ONE} and it is not used in the * current target montage, the channel is removed. * Otherwise an error dialog is shown. */ @Override public void actionPerformed(ActionEvent ev) { ListSelectionModel selectionModel = getSourceMontageTable().getSelectionModel(); if (selectionModel.isSelectionEmpty()) return; int firstRow = selectionModel.getMinSelectionIndex(); int lastRow = selectionModel.getMaxSelectionIndex(); List<Integer> channelsToBeRemoved = new ArrayList<Integer>(); // checking if it is ok to remove rows for (int i = firstRow; i <= lastRow; i++) { if (selectionModel.isSelectedIndex(i)) { IChannelFunction function = montage.getSourceChannelAt(i).getFunction(); if (function != ChannelFunction.ONE && function != ChannelFunction.ZERO) { Dialogs.showError(_("Can only remove ONE and ZERO channels from source montage!")); return; } if (montage.isSourceChannelInUse(i)) { Dialogs.showError(_("This source channel is used in the target montage and cannot be removed.")); return; } channelsToBeRemoved.add(i); } } // remove int numberOfRemovedChannels = 0; for (int channelIndex : channelsToBeRemoved) { montage.removeSourceChannel(channelIndex - numberOfRemovedChannels); numberOfRemovedChannels++; //the channel numbers change after deleting channels that are before them } } } /** * * @author Marcin Szumski * */ protected class ClearMontageAction extends AbstractAction { /** * the default serialization constant */ private static final long serialVersionUID = 1L; /** * Constructor. Sets the text and the icon of this button. */ public ClearMontageAction() { super(_("Clear montage")); putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/clearmontage.png")); } /** * When the action is performed a warning dialog is shown. * If the user confirms the operation, the montage is cleared. */ @Override public void actionPerformed(ActionEvent ev) { if (Dialogs.showWarningYesNoDialog(_("Do you really want to clear the montage?")) == Dialogs.DIALOG_OPTIONS.YES) montage.reset(); } } /** * The popup menu provider for the {@link SourceMontageTable}. * Returns the popup menu with one element - * {@link MontageChannelsPanel#addChannelsAction}. */ protected class SourceMontageTablePopupProvider implements TablePopupMenuProvider { /** * the popup menu with one element - * {@link MontageChannelsPanel#addChannelsAction} */ private JPopupMenu popupMenu; /* (non-Javadoc) * @see org.signalml.app.view.TablePopupMenuProvider#getPopupMenu(int, int) */ @Override public JPopupMenu getPopupMenu(int col, int row) { return getDefaultPopupMenu(); } /* (non-Javadoc) * @see org.signalml.app.view.PopupMenuProvider#getPopupMenu() */ @Override public JPopupMenu getPopupMenu() { return getPopupMenu(-1,-1); } /** * Returns the popup menu with one element - * {@link MontageChannelsPanel#addChannelsAction}. * If the menu doesn't exist it is created. * @return the popup menu with one element - * {@link MontageChannelsPanel#addChannelsAction} */ private JPopupMenu getDefaultPopupMenu() { if (popupMenu == null) { popupMenu = new JPopupMenu(); popupMenu.add(addChannelsAction); } return popupMenu; } } /** * The popup menu provider for the {@link MontageTable}. * Returns the popup menu with 3 elements: * <ul> * <li>{@link MontageChannelsPanel#moveUpAction},</li> * <li>{@link MontageChannelsPanel#moveDownAction},</li> * <li>{@link MontageChannelsPanel#removeChannelsAction}.</li> * </ul> */ protected class MontageTablePopupProvider implements TablePopupMenuProvider { /** * the popup menu with 3 elements: * <ul> * <li>{@link MontageChannelsPanel#moveUpAction},</li> * <li>{@link MontageChannelsPanel#moveDownAction},</li> * <li>{@link MontageChannelsPanel#removeChannelsAction}.</li> * </ul> */ private JPopupMenu popupMenu; /* (non-Javadoc) * @see org.signalml.app.view.TablePopupMenuProvider#getPopupMenu(int, int) */ @Override public JPopupMenu getPopupMenu(int col, int row) { return getDefaultPopupMenu(); } /* (non-Javadoc) * @see org.signalml.app.view.PopupMenuProvider#getPopupMenu() */ @Override public JPopupMenu getPopupMenu() { return getPopupMenu(-1,-1); } /** * Returns the popup menu with 3 elements: * <ul> * <li>{@link MontageChannelsPanel#moveUpAction},</li> * <li>{@link MontageChannelsPanel#moveDownAction},</li> * <li>{@link MontageChannelsPanel#removeChannelsAction}.</li> * </ul> * @return the popup menu with 3 elements: * <ul> * <li>{@link MontageChannelsPanel#moveUpAction},</li> * <li>{@link MontageChannelsPanel#moveDownAction},</li> * <li>{@link MontageChannelsPanel#removeChannelsAction}</li> * </ul> */ private JPopupMenu getDefaultPopupMenu() { if (popupMenu == null) { popupMenu = new JPopupMenu(); popupMenu.add(moveUpAction); popupMenu.add(moveDownAction); popupMenu.addSeparator(); popupMenu.add(removeChannelsAction); } return popupMenu; } } }