/* EditMontageReferencePanel.java created 2007-10-24
*
*/
package org.signalml.app.view.montage.visualreference;
import static org.signalml.app.util.i18n.SvarogI18n._;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.signalml.app.model.montage.MontageTableModel;
import org.signalml.app.util.IconUtils;
import org.signalml.app.util.SwingUtils;
import org.signalml.app.view.common.components.AnyChangeDocumentAdapter;
import org.signalml.app.view.common.components.CompactButton;
import org.signalml.app.view.common.dialogs.errors.Dialogs;
import org.signalml.app.view.montage.MontageTable;
import org.signalml.domain.montage.Montage;
/** EditMontageReferencePanel
*
*
* @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o.
*/
public class VisualReferenceEditorPanel extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
private Montage montage;
private Action previousChannelAction;
private Action nextChannelAction;
private Action acceptWeightAction;
private Action rejectWeightAction;
private Action removeReferenceAction;
private boolean weightTextFieldChanged;
private JTextField weightTextField;
private JCheckBox bipolarCheckBox;
private JButton previousChannelButton;
private JButton nextChannelButton;
private JButton removeReferenceButton;
private CompactButton acceptWeightButton;
private CompactButton rejectWeightButton;
private VisualReferenceModel editorModel;
private VisualReferenceEditor editor;
// private VisualReferenceEditorScrollable editorScrollable;
private JScrollPane editorScrollPane;
private MontageTableModel montageTableModel;
private MontageTable montageTable;
private JScrollPane montageTableScrollPane;
public VisualReferenceEditorPanel() {
super();
initialize();
}
private void initialize() {
previousChannelAction = new PreviousChannelAction();
nextChannelAction = new NextChannelAction();
acceptWeightAction = new AcceptWeightAction();
rejectWeightAction = new RejectWeightAction();
removeReferenceAction = new RemoveReferenceAction();
setLayout(new BorderLayout());
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.setBorder(new CompoundBorder(
new TitledBorder(_("Target montage")),
new EmptyBorder(3,3,3,3)
));
JPanel editorPanel = new JPanel(new BorderLayout());
editorPanel.setBorder(new CompoundBorder(
new TitledBorder(_("Edit reference")),
new EmptyBorder(3,3,3,3)
));
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
controlPanel.setBorder(new EmptyBorder(3,0,0,0));
SwingUtils.makeButtonsSameSize(new JButton[] { getPreviousChannelButton(), getNextChannelButton() });
controlPanel.add(getBipolarCheckBox());
controlPanel.add(Box.createHorizontalStrut(5));
controlPanel.add(Box.createHorizontalGlue());
controlPanel.add(getPreviousChannelButton());
controlPanel.add(Box.createHorizontalStrut(3));
controlPanel.add(getNextChannelButton());
controlPanel.add(Box.createHorizontalStrut(5));
controlPanel.add(Box.createHorizontalGlue());
controlPanel.add(new JLabel(_("Weight")));
controlPanel.add(Box.createHorizontalStrut(3));
controlPanel.add(getWeightTextField());
controlPanel.add(Box.createHorizontalStrut(3));
controlPanel.add(getAcceptWeightButton());
controlPanel.add(Box.createHorizontalStrut(3));
controlPanel.add(getRejectWeightButton());
controlPanel.add(Box.createHorizontalStrut(5));
controlPanel.add(getRemoveReferenceButton());
editorPanel.add(controlPanel, BorderLayout.SOUTH);
editorPanel.add(getEditorScrollPane(), BorderLayout.CENTER);
tablePanel.add(getMontageTableScrollPane(), BorderLayout.CENTER);
add(editorPanel, BorderLayout.CENTER);
add(tablePanel, BorderLayout.EAST);
KeyStroke space = KeyStroke.getKeyStroke("SPACE");
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(space, "NEXT");
getActionMap().put("NEXT", nextChannelAction);
KeyStroke shiftSpace = KeyStroke.getKeyStroke("shift SPACE");
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shiftSpace, "PREVIOUS");
getActionMap().put("PREVIOUS", previousChannelAction);
KeyStroke del = KeyStroke.getKeyStroke("DELETE");
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(del, "removeReference");
getActionMap().put("removeReference", removeReferenceAction);
}
public Montage getMontage() {
return montage;
}
public void setMontage(Montage montage) {
if (this.montage != montage) {
this.montage = montage;
getMontageTableModel().setMontage(montage);
getEditorModel().setMontage(montage);
}
}
public MontageTableModel getMontageTableModel() {
if (montageTableModel == null) {
montageTableModel = new MontageTableModel();
}
return montageTableModel;
}
public MontageTable getMontageTable() {
if (montageTable == null) {
montageTable = new MontageTable(getMontageTableModel(), true);
montageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
montageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int index = montageTable.getSelectedRow();
if (index < 0) {
getEditorModel().setActiveChannel(null);
} else {
getEditorModel().selectChannelAt(index);
Rectangle rect = montageTable.getCellRect(index, 0, true);
montageTable.scrollRectToVisible(rect);
}
}
});
}
return montageTable;
}
public JScrollPane getMontageTableScrollPane() {
if (montageTableScrollPane == null) {
montageTableScrollPane = new JScrollPane(getMontageTable());
montageTableScrollPane.setPreferredSize(new Dimension(150,100));
}
return montageTableScrollPane;
}
public VisualReferenceModel getEditorModel() {
if (editorModel == null) {
editorModel = new VisualReferenceModel();
editorModel.addPropertyChangeListener(this);
}
return editorModel;
}
public VisualReferenceEditor getEditor() {
if (editor == null) {
editor = new VisualReferenceEditor(getEditorModel());
editor.setBackground(Color.WHITE);
}
return editor;
}
/*
public VisualReferenceEditorScrollable getEditorScrollable() {
if( editorScrollable == null ) {
editorScrollable = new VisualReferenceEditorScrollable( getEditor() );
}
return editorScrollable;
}
*/
public JScrollPane getEditorScrollPane() {
if (editorScrollPane == null) {
editorScrollPane = new JScrollPane(getEditor(), JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
getEditor().setViewport(editorScrollPane.getViewport());
}
return editorScrollPane;
}
public JTextField getWeightTextField() {
if (weightTextField == null) {
weightTextField = new JTextField();
weightTextField.setPreferredSize(new Dimension(100,22));
weightTextField.setMaximumSize(new Dimension(100,22));
weightTextField.setMinimumSize(new Dimension(100,22));
weightTextField.getDocument().addDocumentListener(new AnyChangeDocumentAdapter() {
@Override
public void anyUpdate(DocumentEvent e) {
if (!weightTextFieldChanged) {
weightTextFieldChanged = true;
acceptWeightAction.setEnabled(true);
rejectWeightAction.setEnabled(true);
}
}
});
weightTextField.setEnabled(false);
KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
weightTextField.getInputMap(JComponent.WHEN_FOCUSED).put(enter, "ACCEPT");
weightTextField.getActionMap().put("ACCEPT", acceptWeightAction);
weightTextField.getInputMap(JComponent.WHEN_FOCUSED).put(escape, "REJECT");
weightTextField.getActionMap().put("REJECT", rejectWeightAction);
}
return weightTextField;
}
public JCheckBox getBipolarCheckBox() {
if (bipolarCheckBox == null) {
bipolarCheckBox = new JCheckBox(_("Bipolar mode"));
bipolarCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getEditorModel().setBipolarMode(bipolarCheckBox.isSelected());
}
});
bipolarCheckBox.setEnabled(false);
}
return bipolarCheckBox;
}
public JButton getPreviousChannelButton() {
if (previousChannelButton == null) {
previousChannelButton = new JButton(previousChannelAction);
previousChannelButton.setHorizontalAlignment(JButton.CENTER);
previousChannelButton.setContentAreaFilled(false);
previousChannelButton.setMargin(new Insets(0,5,0,5));
}
return previousChannelButton;
}
public JButton getNextChannelButton() {
if (nextChannelButton == null) {
nextChannelButton = new JButton(nextChannelAction);
nextChannelButton.setHorizontalTextPosition(JButton.LEADING);
nextChannelButton.setHorizontalAlignment(JButton.CENTER);
nextChannelButton.setContentAreaFilled(false);
nextChannelButton.setMargin(new Insets(0,5,0,5));
}
return nextChannelButton;
}
public JButton getRemoveReferenceButton() {
if (removeReferenceButton == null) {
removeReferenceButton = new JButton(removeReferenceAction);
removeReferenceButton.setContentAreaFilled(false);
removeReferenceButton.setMargin(new Insets(0,5,0,5));
}
return removeReferenceButton;
}
public CompactButton getAcceptWeightButton() {
if (acceptWeightButton == null) {
acceptWeightButton = new CompactButton(acceptWeightAction);
}
return acceptWeightButton;
}
public CompactButton getRejectWeightButton() {
if (rejectWeightButton == null) {
rejectWeightButton = new CompactButton(rejectWeightAction);
}
return rejectWeightButton;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
Object source = evt.getSource();
VisualReferenceModel editorModel = getEditorModel();
if (source == editorModel) {
String name = evt.getPropertyName();
if (VisualReferenceModel.BIPOLAR_COMPATIBLE_PROPERTY.equals(name)) {
boolean bipolarCompatible = editorModel.isBipolarCompatible();
JCheckBox checkBox = getBipolarCheckBox();
if (!bipolarCompatible && checkBox.isSelected()) {
checkBox.setSelected(false);
}
checkBox.setEnabled(bipolarCompatible);
}
else if (VisualReferenceModel.ACTIVE_ARROW_PROPERTY.equals(name)) {
VisualReferenceArrow arrow = (VisualReferenceArrow) evt.getNewValue();
JTextField textField = getWeightTextField();
if (arrow == null) {
textField.setText("");
textField.setEnabled(false);
} else {
String weight = montage.getReference(arrow.getTargetChannel(), arrow.getSourceChannel());
if (weight != null) {
textField.setText(weight);
} else {
textField.setText("");
}
textField.setEnabled(true);
}
weightTextFieldChanged = false;
acceptWeightAction.setEnabled(false);
rejectWeightAction.setEnabled(false);
removeReferenceAction.setEnabled(arrow != null);
}
else if (VisualReferenceModel.ACTIVE_CHANNEL_PROPERTY.equals(name)) {
VisualReferenceChannel channel = (VisualReferenceChannel) evt.getNewValue();
if (channel == null) {
getMontageTable().clearSelection();
} else {
int index = getEditorModel().indexOfChannel(channel);
if (index < 0) {
getMontageTable().clearSelection();
} else {
getMontageTable().getSelectionModel().setSelectionInterval(index, index);
}
}
}
}
}
protected class PreviousChannelAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public PreviousChannelAction() {
super(_("Previous"));
putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/previous.png"));
putValue(AbstractAction.SHORT_DESCRIPTION,_("Previous channel (Shift-Space)"));
}
public void actionPerformed(ActionEvent ev) {
getEditorModel().selectPreviousChannel();
}
}
protected class NextChannelAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public NextChannelAction() {
super(_("Next"));
putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/next.png"));
putValue(AbstractAction.SHORT_DESCRIPTION,_("Next channel (Space)"));
}
public void actionPerformed(ActionEvent ev) {
getEditorModel().selectNextChannel();
}
}
protected class RemoveReferenceAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public RemoveReferenceAction() {
super(_("Remove"));
putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/removereference.png"));
putValue(AbstractAction.SHORT_DESCRIPTION,_("Remove this reference (Delete)"));
setEnabled(false);
}
public void actionPerformed(ActionEvent ev) {
VisualReferenceModel model = getEditorModel();
VisualReferenceArrow selArrow = model.getActiveArrow();
if (selArrow == null) {
return;
}
model.removeReference(selArrow.getTargetChannel(), selArrow.getSourceChannel());
model.setActiveArrow(null);
}
}
protected class AcceptWeightAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public AcceptWeightAction() {
super();
putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/ok.png"));
putValue(AbstractAction.SHORT_DESCRIPTION,_("Accept edit"));
setEnabled(false);
}
public void actionPerformed(ActionEvent ev) {
if (montage == null) {
return;
}
VisualReferenceArrow arrow = getEditorModel().getActiveArrow();
if (arrow == null) {
return;
}
try {
montage.setReference(arrow.getTargetChannel(), arrow.getSourceChannel(), weightTextField.getText());
} catch (NumberFormatException ex) {
Dialogs.showExceptionDialog((Window) null, ex);
weightTextField.setText(montage.getReference(arrow.getTargetChannel(), arrow.getSourceChannel()));
weightTextField.selectAll();
weightTextField.requestFocusInWindow();
}
weightTextFieldChanged = false;
acceptWeightAction.setEnabled(false);
rejectWeightAction.setEnabled(false);
}
}
protected class RejectWeightAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public RejectWeightAction() {
super();
putValue(AbstractAction.SMALL_ICON, IconUtils.loadClassPathIcon("org/signalml/app/icon/cancel.png"));
putValue(AbstractAction.SHORT_DESCRIPTION,_("Discard edit"));
setEnabled(false);
}
public void actionPerformed(ActionEvent ev) {
if (montage == null) {
return;
}
VisualReferenceArrow arrow = getEditorModel().getActiveArrow();
if (arrow == null) {
return;
}
weightTextField.setText(montage.getReference(arrow.getTargetChannel(), arrow.getSourceChannel()));
weightTextFieldChanged = false;
acceptWeightAction.setEnabled(false);
rejectWeightAction.setEnabled(false);
}
}
}