package org.signalml.app.view.document.opensignal.elements; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.BorderLayout; import java.awt.Window; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import org.signalml.app.model.document.opensignal.AbstractOpenSignalDescriptor; import org.signalml.app.model.document.opensignal.ExperimentDescriptor; import org.signalml.app.model.document.opensignal.SignalMLDescriptor; import org.signalml.app.model.document.opensignal.elements.AmplifierChannel; import org.signalml.app.model.document.opensignal.elements.SignalParameters; import org.signalml.app.view.common.dialogs.AbstractDialog; import org.signalml.app.view.document.monitor.ChannelDefinition; import org.signalml.app.view.document.monitor.ChannelDefinitionsTable; import org.signalml.domain.signal.raw.RawSignalDescriptor; /** * A dialog that allows to edit gain and offset. * * @author Tomasz Sawicki */ public class EditGainAndOffsetDialog extends AbstractDialog { /** * The definition table. */ private ChannelDefinitionsTable definitionsTable; /** * Default constructor sets window's title. */ public EditGainAndOffsetDialog(Window w, boolean m) { super(w, m); setTitle(_("Edit gain and offset")); } /** * Dialog can be filled from {@link ExperimentDescriptor}, {@link RawSignalDescriptor} * or {@link AmplifierConnectionDescriptor}. * * @param clazz checked model * @return true if SignalParametersDescriptor is assignable from clazz */ @Override public boolean supportsModelClass(Class<?> clazz) { return AbstractOpenSignalDescriptor.class.isAssignableFrom(clazz); } /** * Fills the dialog from a {@link SignalParametersDescriptor} object. * * @param model the descriptor */ @Override public void fillDialogFromModel(Object model) { if (model instanceof ExperimentDescriptor) { fillDialogForOpenBCIConnection((ExperimentDescriptor) model); } else if (model instanceof RawSignalDescriptor) { fillDialogForFileOpening((RawSignalDescriptor) model); } } /** * Fills a {@link SignalParametersDescriptor} from the dialog. * * @param model the descriptor */ @Override public void fillModelFromDialog(Object model) { if (model instanceof ExperimentDescriptor) { fillModelForOpenBCIConnection((ExperimentDescriptor) model); } else if (model instanceof RawSignalDescriptor) { fillModelForFileOpening((RawSignalDescriptor) model); } } /** * Fills the dialog for BCI connection. * * @param descriptor the descriptor */ private void fillDialogForOpenBCIConnection(ExperimentDescriptor descriptor) { int i = 0; List<ChannelDefinition> definitions = new ArrayList<ChannelDefinition>(); for (AmplifierChannel channel: descriptor.getAmplifier().getSelectedChannels()) { definitions.add(new ChannelDefinition( i+1, channel.getCalibrationGain(), channel.getCalibrationOffset(), channel.getLabel())); i++; } getDefinitionsTable().setData(definitions); } /** * Fills the dialog for file opening. * * @param descriptor the descriptor */ private void fillDialogForFileOpening(RawSignalDescriptor descriptor) { if (descriptor.getChannelLabels() != null) { setAllGainAndOffsetEditable(true); List<ChannelDefinition> definitions = new ArrayList<ChannelDefinition>(); for (int i = 0; i < descriptor.getChannelCount(); i++) { definitions.add(new ChannelDefinition( i+1, descriptor.getCalibrationGain()[i], descriptor.getCalibrationOffset()[i], descriptor.getChannelLabels()[i])); } getDefinitionsTable().setData(definitions); } } /** * Fills the model for BCI connection. * * @param descriptor the descriptor */ private void fillModelForOpenBCIConnection(ExperimentDescriptor descriptor) { float[] gains = getGainArray(); float[] offsets = getOffsetArray(); int i = 0; for (AmplifierChannel channel: descriptor.getAmplifier().getSelectedChannels()) { channel.setCalibrationGain(gains[i]); channel.setCalibrationOffset(offsets[i]); i++; } } /** * Fills the model for file opening. * * @param descriptor the descriptor */ private void fillModelForFileOpening(RawSignalDescriptor descriptor) { descriptor.setCalibrationGain(getGainArray()); descriptor.setCalibrationOffset(getOffsetArray()); } /** * Gets gain as a float array. * * @return gain as a float array */ private float[] getGainArray() { Float[] gainFromList = getDefinitionsTable().getGainValues().toArray(new Float[0]); float[] gain = new float[gainFromList.length]; for (int i = 0; i < gainFromList.length; i++) { gain[i] = gainFromList[i]; } return gain; } /** * Gets offset as a float array. * * @return offset as a float array */ private float[] getOffsetArray() { Float[] offsetFromList = getDefinitionsTable().getOffsetValues().toArray(new Float[0]); float[] offset = new float[offsetFromList.length]; for (int i = 0; i < offsetFromList.length; i++) { offset[i] = offsetFromList[i]; } return offset; } /** * Creates the interface (the {@link #editDefinitionPanel} * * @return the interface panel */ @Override protected JComponent createInterface() { JPanel mainPanel = new JPanel(new BorderLayout()); CompoundBorder border = new CompoundBorder( new TitledBorder(""), new EmptyBorder(3, 3, 3, 3)); mainPanel.setBorder(border); mainPanel.setLayout(new BorderLayout(10, 10)); mainPanel.add(new JScrollPane(getDefinitionsTable()), BorderLayout.CENTER); return mainPanel; } /** * Returns the edit definition panel. * * @return the edit definiiton panel */ private ChannelDefinitionsTable getDefinitionsTable() { if (definitionsTable == null) { definitionsTable = new ChannelDefinitionsTable(true); } return definitionsTable; } /** * Wheter all gain and offset values can be edited. * * @param editable if true, all values can be edited. If false, * only one value can be edited and will be applied to all channels. */ private void setAllGainAndOffsetEditable(boolean editable) { if (!editable) { List<ChannelDefinition> list = new ArrayList<ChannelDefinition>(); list.add(new ChannelDefinition(0, 0.0f, 0.0f, "0")); getDefinitionsTable().setData(list); } getDefinitionsTable().setAllEditable(editable); } /** * Gets the gain. Used only if only one gain and offset is editable. * * @return the gain */ private float getGain() { return getDefinitionsTable().getData().get(0).getGain(); } /** * Gets the offset. Used only if only one gain and offset is editable. * * @return the offset */ private float getOffset() { return getDefinitionsTable().getData().get(0).getOffset(); } /** * Sets the gain. Used only if only one gain and offset is editable. * * @param gain the gain */ private void setGain(float gain) { ChannelDefinition definition = getDefinitionsTable().getData().get(0); definition.setGain(gain); List<ChannelDefinition> list = new ArrayList<ChannelDefinition>(); list.add(definition); getDefinitionsTable().setData(list); getDefinitionsTable().setAllEditable(false); } /** * Sets the offset. Used only if only one gain and offset is editable. * * @param offset the offset */ private void setOffset(float offset) { ChannelDefinition definition = getDefinitionsTable().getData().get(0); definition.setOffset(offset); List<ChannelDefinition> list = new ArrayList<ChannelDefinition>(); list.add(definition); getDefinitionsTable().setData(list); getDefinitionsTable().setAllEditable(false); } }