/* Montage.java created 2007-10-23
*
*/
package org.signalml.domain.montage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import org.signalml.app.config.preset.Preset;
import org.signalml.app.document.signal.SignalDocument;
import org.signalml.domain.montage.filter.FFTSampleFilter;
import org.signalml.domain.montage.filter.SampleFilterDefinition;
import org.signalml.domain.montage.filter.TimeDomainSampleFilter;
import org.signalml.domain.montage.generators.IMontageGenerator;
import org.signalml.domain.montage.system.ChannelFunction;
import org.signalml.domain.montage.system.IChannelFunction;
import org.signalml.util.Util;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* This class represents the signal montage.
* Montage is the representation of the EEG channels.
* Every montage channel is a difference between the voltage of the electrode
* and voltage of some reference (may be another electrode or average of electrodes).
*
* This class contains a list of {@link MontageChannel montage channels} and
* a list of {@link MontageSampleFilter filters}.
* Filters can be excluded either for selected channels or for all of them.
* This class has also assigned listeners informing about changes in a montage.
*
* @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o.
*/
@XStreamAlias("montage")
public class Montage extends SourceMontage implements Preset {
private static final long serialVersionUID = 1L;
public static final String MONTAGE_GENERATOR_PROPERTY = "montageGenerator";
public static final String NAME_PROPERTY = "montageGenerator";
public static final String DESCRIPTION_PROPERTY = "description";
public static final String MAJOR_CHANGE_PROPERTY = "majorChange";
public static final String FILTERING_ENABLED_PROPERTY = "filteringEnabled";
public static final String FILTFILT_ENABLED_PROPERTY = "filtfiltEnabled";
/**
* string representing the name of the montage
*/
private String name;
/**
* string containing the description of the montage
*/
private String description;
/**
* {@link MontageGenerator generator} for the current object
*/
private IMontageGenerator montageGenerator;
/**
* {@link MontageChannel montaged channels} of a signal in the montage
*/
private ArrayList<MontageChannel> montageChannels;
/**
* HashMap associating {@link SourceChannel source channels} with
* the list of MontageChannels for which these channels are
* primaryChannels
*/
private transient HashMap<SourceChannel,LinkedList<MontageChannel>> montageChannelsByPrimary;
/**
* HashMap associating {@link MontageChannel montage channels}
* with their labels
*/
private transient HashMap<String,MontageChannel> montageChannelsByLabel;
/**
* the list of {@link MontageSampleFilter filters}
*/
private ArrayList<MontageSampleFilter> filters = new ArrayList<MontageSampleFilter>();
/**
* tells whether the signal is being filtered
*/
private boolean filteringEnabled = true;
/**
* tells whether the signal should be filtered using filtfilt
*/
private boolean filtfiltEnabled = true;
/**
* tells whether montage is undergoing a major change
*/
private transient boolean majorChange = false;
/**
* Constructor. Creates an empty Montage.
*/
protected Montage() {
super();
}
/**
* Copy constructor.
* @param montage the montage to be copied
*/
public Montage(Montage montage) {
this();
copyFrom(montage);
}
/**
* Copy constructor. Creates a Montage from the given
* {@link SourceMontage SourceMontage (superclass)}
* @param sourceMontage SourceMontage object to be copied as Montage
*/
public Montage(SourceMontage sourceMontage) {
this();
super.copyFrom(sourceMontage);
montageChannels = new ArrayList<MontageChannel>();
}
/**
* Constructor. Creates Montage from the document with a signal.
* @param document the document with a signal
*/
public Montage(SignalDocument document) {
super(document);
montageChannels = new ArrayList<MontageChannel>();
}
/**
* Creates a copy of this montage.
* @return the created copy
*/
@Override
public Montage clone() {
Montage montage = new Montage();
montage.copyFrom(this);
return montage;
}
/**
* Copies parameters of the given Montage to this montage.
* MontageChannels and filters are also copied.
* Listeners are not copied.
* @param montage the Montage which parameters are to be copied to
* this montage
*/
protected void copyFrom(Montage montage) {
super.copyFrom(montage);
montageChannels = new ArrayList<MontageChannel>(montage.montageChannels.size());
HashMap<String, MontageChannel> map = getMontageChannelsByLabel();
map.clear();
getMontageChannelsByPrimary().clear();
MontageChannel newChannel;
LinkedList<MontageChannel> list;
for (MontageChannel channel : montage.montageChannels) {
newChannel = new MontageChannel(channel, sourceChannels);
list = getMontageChannelsByPrimaryList(newChannel.getPrimaryChannel());
montageChannels.add(newChannel);
map.put(newChannel.getLabel(), newChannel);
list.add(newChannel);
}
if (montage.filters != null) {
filters = new ArrayList<MontageSampleFilter>(montage.filters.size());
MontageSampleFilter newFilter;
for (MontageSampleFilter filter : montage.filters) {
newFilter = new MontageSampleFilter(filter, montageChannels, montage.montageChannels);
filters.add(newFilter);
}
} else {
filters = new ArrayList<MontageSampleFilter>();
}
filteringEnabled = montage.filteringEnabled;
filtfiltEnabled = montage.filtfiltEnabled;
setName(montage.name);
setDescription(montage.description);
setMontageGenerator(montage.montageGenerator);
fireMontageStructureChanged(this);
}
/**
* Checks if this montage is compatible with the object given as parameter.
* Montages are compatible if:
* 1. they are compatible as {@link SourceMontage source montages}
* 2. have the same number of montage channels
* 3. for each source channel montage channels have the same references
* @param montage the montage to be compared with a current object
* @return true if montages are compatible, false otherwise
*/
public boolean isCompatible(Montage montage) {
boolean sourceCompatible = super.isCompatible(montage);
if (!sourceCompatible) {
return false;
}
int cnt = getMontageChannelCount();
int mCnt = montage.getMontageChannelCount();
if (cnt != mCnt) {
// different montage channel count
return false;
}
// now for each source channel check that the montage channels
// in each montage have same references. Order, labels don't matter
int srcCnt = getSourceChannelCount();
int i;
LinkedList<MontageChannel> ourChannels;
LinkedList<MontageChannel> theirChannels;
int ourSize;
int theirSize;
boolean found;
MontageChannel our;
Iterator<MontageChannel> theirIt;
Iterator<MontageChannel> ourIt;
for (i=0; i<srcCnt; i++) {
ourChannels = getMontageChannelsByPrimaryList(sourceChannels.get(i));
theirChannels = montage.getMontageChannelsByPrimaryList(montage.sourceChannels.get(i));
ourSize = ourChannels.size();
theirSize = theirChannels.size();
if (ourSize != theirSize) {
// different montage channel count
return false;
}
if (ourSize == 0) {
continue;
}
ourIt = ourChannels.iterator();
while (ourIt.hasNext()) {
our = ourIt.next();
theirIt = theirChannels.iterator();
found = false;
while (theirIt.hasNext()) {
if (our.isEqualReference(theirIt.next(), montage.sourceChannels)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
}
return true;
}
/**
* Resets all parameters of the current object.
*/
public void reset() {
getMontageChannelsByLabel().clear();
getMontageChannelsByPrimary().clear();
montageChannels.clear();
for (MontageSampleFilter filter : filters) {
filter.clearExclusion();
}
if (!majorChange) {
fireMontageStructureChanged(this);
fireMontageSampleFiltersChanged(this);
}
setMontageGenerator(null);
setChanged(true);
}
/**
* Returns the name of this montage.
* @return the name of this montage
*/
@Override
public String getName() {
return name;
}
/**
* Sets the name of this montage.
* @param name String with the name to be set
*/
@Override
public void setName(String name) {
if (!Util.equalsWithNulls(this.name, name)) {
String oldName = this.name;
this.name = name;
pcSupport.firePropertyChange(NAME_PROPERTY, oldName, name);
setChanged(true);
}
}
/**
* Returns the description of this montage.
* @return the description of this montage
*/
public String getDescription() {
return description;
}
/**
* Sets the description of this montage.
* @param description String with the description to be set
*/
public void setDescription(String description) {
if (!Util.equalsWithNulls(this.description, description)) {
String oldDescription = this.description;
this.description = description;
pcSupport.firePropertyChange(DESCRIPTION_PROPERTY, oldDescription, description);
setChanged(true);
}
}
/**
* Returns the generator for the this montage.
* @return the generator for the this montage
*/
public IMontageGenerator getMontageGenerator() {
return montageGenerator;
}
/**
* Sets the new {@link MontageGenerator generator} for this montage.
* @param montageGenerator generator to be set
*/
public void setMontageGenerator(IMontageGenerator montageGenerator) {
if (!Util.equalsWithNulls(this.montageGenerator, montageGenerator)) {
IMontageGenerator oldGenerator = this.montageGenerator;
this.montageGenerator = montageGenerator;
pcSupport.firePropertyChange(MONTAGE_GENERATOR_PROPERTY, oldGenerator, montageGenerator);
setChanged(true);
}
}
/**
* Returns whether this montage is undergoing a major change.
* @return true this montage is undergoing a major change,
* false otherwise
*/
public boolean isMajorChange() {
return majorChange;
}
/**
* Sets the majorChange property to a given value
* @param majorChange the value to be set
*/
public void setMajorChange(boolean majorChange) {
if (this.majorChange != majorChange) {
this.majorChange = majorChange;
pcSupport.firePropertyChange(MAJOR_CHANGE_PROPERTY, !majorChange, majorChange);
if (!majorChange) {
// turned off
fireMontageStructureChanged(this);
fireMontageSampleFiltersChanged(this);
setChanged(true);
}
}
}
/**
* Tells whether the signal is being filtered.
* @return true if signal is being filtered, false otherwise
*/
public boolean isFilteringEnabled() {
return filteringEnabled;
}
/**
* Sets the filteringEnabled property to a given value.
* @param filteringEnabled the value to be set
*/
public void setFilteringEnabled(boolean filteringEnabled) {
if (this.filteringEnabled != filteringEnabled) {
this.filteringEnabled = filteringEnabled;
pcSupport.firePropertyChange(FILTERING_ENABLED_PROPERTY, !filteringEnabled, filteringEnabled);
}
}
/**
* Tells whether the signal should be filtered using filtfilt.
* @return true if the signal should be filtered using filtfilt, false
* otherwise
*/
public boolean isFiltfiltEnabled() {
return filtfiltEnabled;
}
/**
* Sets the filtfiltEnabled property to a given value.
* @param filtfiltEnabled the value to be set
*/
public void setFiltfiltEnabled(boolean filtfiltEnabled) {
if (this.filtfiltEnabled != filtfiltEnabled) {
this.filtfiltEnabled = filtfiltEnabled;
pcSupport.firePropertyChange(FILTFILT_ENABLED_PROPERTY, !filtfiltEnabled, filtfiltEnabled);
}
}
/**
* Returns the name of this montage.
* @return String with the name of this montage.
*/
@Override
public String toString() {
return name;
}
/**
* Returns HashMap associating {@link SourceChannel source channels} with
* the list of {@link MontageChannel montage channels} for which these
* channels are primaryChannels.
* @return HashMap associating source channels with
* the list of montage channels for which these channels are
* primaryChannels
*/
protected HashMap<SourceChannel, LinkedList<MontageChannel>> getMontageChannelsByPrimary() {
if (montageChannelsByPrimary == null) {
montageChannelsByPrimary = new HashMap<SourceChannel, LinkedList<MontageChannel>>();
}
return montageChannelsByPrimary;
}
/**
* Returns the list of {@link MontageChannel montage channels} for which
* the given {@link SourceChannel source channel} is a primary channel.
* @param channel the source channel object for which list is returned
* @return the list of montage channels for which given source channel
* is a primary channel
*/
protected LinkedList<MontageChannel> getMontageChannelsByPrimaryList(SourceChannel channel) {
HashMap<SourceChannel, LinkedList<MontageChannel>> map = getMontageChannelsByPrimary();
LinkedList<MontageChannel> list = map.get(channel);
if (list == null) {
list = new LinkedList<MontageChannel>();
map.put(channel, list);
for (MontageChannel montageChannel : montageChannels) {
if (montageChannel.getPrimaryChannel() == channel) {
list.add(montageChannel);
}
}
}
return list;
}
/**
* Returns the {@link SourceChannel} for the montage channel having the
* given index.
* @param index the index of the montage channel
* @return the {@link SourceChannel} associated with the given montage
* channel
*/
public SourceChannel getSourceChannelForMontageChannel(int index) {
int primaryChannelIndex = getMontagePrimaryChannelAt(index);
SourceChannel sourceChannel = getSourceChannelAt(primaryChannelIndex);
return sourceChannel;
}
/**
* Returns HashMap associating {@link MontageChannel montage channels}
* with their labels.
* @return HashMap associating montage channels with their labels
*/
protected HashMap<String,MontageChannel> getMontageChannelsByLabel() {
if (montageChannelsByLabel == null) {
montageChannelsByLabel = new HashMap<String, MontageChannel>();
for (MontageChannel channel : montageChannels) {
montageChannelsByLabel.put(channel.getLabel(), channel);
}
}
return montageChannelsByLabel;
}
/**
* Finds a {@link MontageChannel montage channel} with a given label.
* @param label String with a label to be found
* @return the found montage channel
*/
protected MontageChannel getMontageChannelByLabel(String label) {
return getMontageChannelsByLabel().get(label);
}
/**
* Returns the number of {@link MontageChannel montage channels}
* in the montage.
* @return the number of montage channels in the montage
*/
public int getMontageChannelCount() {
return montageChannels.size();
}
/**
* Returns the index of primary channel for selected
* {@link MontageChannel montage channel}.
* @param index the index of montage channel
* @return found index of primary channel
*/
public int getMontagePrimaryChannelAt(int index) {
return montageChannels.get(index).getPrimaryChannel().getChannel();
}
/**
* Returns the label of a {@link MontageChannel montage channel}
* at a given index.
* @param index the index of a montage channel
* @return the label of a montage channel
*/
public String getMontageChannelLabelAt(int index) {
return montageChannels.get(index).getLabel();
}
/**
* Returns the index of the montage channel that has
* the specified label.
* @param label the label of the montage channel that is search for
* @return the index of the montage channel
*/
public int getMontageChannelIndex(String label) {
for (int i = 0; i < montageChannels.size(); i++) {
if (montageChannels.get(i).getLabel().equals(label))
return i;
}
return -1;
}
/**
* Sets a new label for a {@link MontageChannel montage channel}
* at a given index.
* @param index the index of a montage channel
* @param label a new label to be set
* @return the old label
* @throws MontageException if the label empty,
* with illegal characters or not unique
*/
public String setMontageChannelLabelAt(int index, String label) throws MontageException {
if (label == null || label.isEmpty()) {
throw new MontageException("error.montageChannelLabelEmpty");
}
if (Util.hasSpecialChars(label)) {
throw new MontageException("error.montageChannelLabelBadChars");
}
MontageChannel channel = montageChannels.get(index);
String oldLabel = channel.getLabel();
HashMap<String, MontageChannel> map = getMontageChannelsByLabel();
if (!oldLabel.equals(label)) {
MontageChannel namedChannel = map.get(label);
if (namedChannel != null && namedChannel != channel) {
throw new MontageException("error.montageChannelLabelDuplicate");
}
map.remove(oldLabel);
channel.setLabel(label);
map.put(label, channel);
if (!majorChange) {
fireMontageChannelsChanged(this, new int[] { index }, new int[] { channel.getPrimaryChannel().getChannel() });
setChanged(true);
}
setMontageGenerator(null);
}
return oldLabel;
}
/**
* Checks whether the {@link SourceChannel source channel} of a given
* index is in use, i.e. either is a primaryChannel for some
* {@link MontageChannel montage channel}, or there is a reference
* to it in a montage channel.
* @param index the index of source channel
* @return true if the source channel is in use, false otherwise
*/
public boolean isSourceChannelInUse(int index) {
SourceChannel channel = sourceChannels.get(index);
if (!getMontageChannelsByPrimaryList(channel).isEmpty()) {
return true;
}
for (MontageChannel montageChannel : montageChannels) {
if (montageChannel.hasReference(channel)) {
return true;
}
}
return false;
}
/**
* Checks if a given {@link MontageChannel montage channel} has
* a reference to a given {@link SourceChannel source channel}.
* @param montageIndex an index of a montage channel
* @param sourceIndex an index of a source channel
* @return true if there is a reference, false otherwise
*/
public boolean hasReference(int montageIndex, int sourceIndex) {
return montageChannels.get(montageIndex).hasReference(sourceChannels.get(sourceIndex));
}
/**
* Checks if a given {@link MontageChannel montage channel} has
* a reference to any {@link SourceChannel source channel}.
* @param montageIndex an index of montage channel
* @return true if there is a reference, false otherwise
*/
public boolean hasReference(int montageIndex) {
return montageChannels.get(montageIndex).hasReference();
}
/**
* Returns a list of {@link MontageChannel montage channels} for which
* a {@link SourceChannel source channel} of a given index
* is a primary channel.
* @param index an index of a source channel
* @return a list of montage channels for which source channel of
* a given index is a primary channel
*/
public int[] getMontageChannelsForSourceChannel(int index) {
SourceChannel channel = sourceChannels.get(index);
LinkedList<MontageChannel> list = getMontageChannelsByPrimaryList(channel);
int[] result = new int[list.size()];
int cnt = 0;
for (MontageChannel montageChannel : list) {
result[cnt] = montageChannels.indexOf(montageChannel);
cnt++;
}
return result;
}
/**
* Creates a unique label for a {@link MontageChannel montage channel}
* based on a given String
* @param stem String object on which a new label will be based
* @return created unique label
*/
public String getNewMontageChannelLabel(String stem) {
int cnt = 2;
String candidate = stem;
HashMap<String, MontageChannel> map = getMontageChannelsByLabel();
while (map.containsKey(candidate)) {
candidate = stem + " (" + cnt + ")";
cnt++;
}
return candidate;
}
/**
* For a {@link MontageChannel montage channel} of a given index,
* returns an array of references in the form of Strings
* @param index an index of the montage channel
* @return an array of references for a montage channel of a given index
*/
public String[] getReference(int index) {
String[] references = new String[sourceChannels.size()];
montageChannels.get(index).getReferences(references);
return references;
}
/**
* For a {@link MontageChannel montage channel} of a given index,
* returns a string representing its references
* @param index an index of the montage channel
* @return a string representing channel's references
*/
public String getReferenceReadable(int index) {
String[] references = new String[sourceChannels.size()];
montageChannels.get(index).getReferences(references);
String result = ""; // start with the first element
String ONE = "1", MINUS = "-";
for (int i=0; i<references.length; i++) {
if ((references[i] == null) || (this.getSourceChannelAt(i).getFunction() == ChannelFunction.ZERO))
// null means that no reference for given sourceChannel is present
// empty is 0 - also ignore
continue;
else {
// combine current reference with other - insert '*' chars etc
String pre = "";
if ((references[i].startsWith(MINUS)) || (result.length() == 0))
pre = "";
else
pre = "+";
if (!references[i].equals(ONE))
pre = pre + references[i] + "*";
if (this.getSourceChannelAt(i).getFunction() == ChannelFunction.ONE)
result = result + pre + "1";
else
result = result + pre + sourceChannels.get(i).getLabel();
}
}
return result;
}
/**
* For a {@link MontageChannel montage channel} of a given index,
* returns an array of references in the form of floats
* (converted from Strings).
* @param index an index of MontageChannel object
* @return an array of references for a MontageChannel of a given index
*/
public float[] getReferenceAsFloat(int index) {
float[] references = new float[sourceChannels.size()];
montageChannels.get(index).getReferencesAsFloat(references);
return references;
}
/**
* Sets a new array of references for a
* {@link MontageChannel montage channel} of a given index.
* @param index an index of a montage channel
* @param references a list of references in the form of Strings
* @throws NumberFormatException if the references array is to long
* (larger then the number of source channels)
*/
public void setReference(int index, String[] references) throws NumberFormatException {
if (references.length > sourceChannels.size()) {
throw new IndexOutOfBoundsException("References too long [" + references.length + "]");
}
MontageChannel channel = montageChannels.get(index);
channel.setReferences(references, sourceChannels);
if (!majorChange) {
fireMontageReferenceChanged(this, new int[] { index }, new int[] { channel.getPrimaryChannel().getChannel() });
setChanged(true);
}
setMontageGenerator(null);
}
/**
* Returns the reference between a given
* {@link MontageChannel montage channel} and a given
* {@link SourceChannel source channel}.
* @param montageIndex an index of montage channel
* @param sourceIndex an index of source channel
* @return reference between a given montage channel and
* a given source channel
*/
public String getReference(int montageIndex, int sourceIndex) {
return montageChannels.get(montageIndex).getReference(sourceChannels.get(sourceIndex));
}
/**
* Checks if the reference between a given
* {@link MontageChannel montage channel} and
* a given {@link SourceChannel source channel} is symmetric.
* @param montageIndex an index of montage channel
* @param sourceIndex an index of source channel
* @return true if the reference is symmetric, false otherwise
*/
public boolean isReferenceSymmetric(int montageIndex, int sourceIndex) {
return montageChannels.get(montageIndex).isSymmetricWeight(sourceChannels.get(sourceIndex));
}
/**
* Sets the reference between a given
* {@link MontageChannel montage channel} and
* a given {@link SourceChannel source channel} to a given value.
* @param montageIndex an index of a montage channel
* @param sourceIndex an index of a source channel
* @param value the value of reference to be set
* @throws NumberFormatException thrown when the references array is
* to long (larger then the number of source channels)
*/
public void setReference(int montageIndex, int sourceIndex, String value) throws NumberFormatException {
MontageChannel channel = montageChannels.get(montageIndex);
channel.setReference(sourceChannels.get(sourceIndex), value);
if (!majorChange) {
fireMontageReferenceChanged(this, new int[] { montageIndex }, new int[] { channel.getPrimaryChannel().getChannel() });
setChanged(true);
}
setMontageGenerator(null);
}
/**
* Removes the reference between a given
* {@link MontageChannel montage channel} and
* a given {@link SourceChannel source channel}.
* @param montageIndex an index of a montage channel
* @param sourceIndex an index of a source channel
*/
public void removeReference(int montageIndex, int sourceIndex) {
MontageChannel channel = montageChannels.get(montageIndex);
channel.removeReference(sourceChannels.get(sourceIndex));
if (!majorChange) {
fireMontageReferenceChanged(this, new int[] { montageIndex }, new int[] { channel.getPrimaryChannel().getChannel() });
setChanged(true);
}
setMontageGenerator(null);
}
/**
* Adds a new {@link SourceChannel source channel} with a given label
* and function to the list of source channels.
* @param label a unique label for new source channel
* @param function a unique function for new source channel
* @throws MontageException if a label or function not unique
*/
@Override
public void addSourceChannel(String label, IChannelFunction function) throws MontageException {
super.addSourceChannel(label, function);
setMontageGenerator(null);
}
@Override
public boolean removeSourceChannel(int index) {
if (isSourceChannelInUse(index)) {
return false;
}
else {
return super.removeSourceChannel(index);
}
}
/**
* Removes the last {@link SourceChannel source channel} on the the list
* of source channels, montage channels with it as a primary and
* all references to it.
* @return removed source channel
*/
@Override
protected SourceChannel removeLastSourceChannel() {
if (sourceChannels.isEmpty()) {
return null;
}
SourceChannel channel = sourceChannels.get(sourceChannels.size() - 1) ;
LinkedList<MontageChannel> list = getMontageChannelsByPrimaryList(channel);
MontageChannel montageChannel;
if (!list.isEmpty()) {
int[] indices = new int[list.size()];
int[] primaryIndices = new int[indices.length];
int cnt = 0;
Iterator<MontageChannel> it = list.iterator();
while (it.hasNext()) {
montageChannel = it.next();
indices[cnt] = montageChannels.indexOf(montageChannel);
primaryIndices[cnt] = montageChannel.getPrimaryChannel().getChannel();
cnt++;
}
it = list.iterator();
HashMap<String, MontageChannel> map = getMontageChannelsByLabel();
LinkedList<Integer> filterIndexList = new LinkedList<Integer>();
int filterCnt = filters.size();
int i;
while (it.hasNext()) {
montageChannel = it.next();
map.remove(montageChannel.getLabel());
montageChannels.remove(montageChannel);
for (i=0; i<filterCnt; i++) {
if (filters.get(i).removeExcludedChannel(montageChannel)) {
if (!filterIndexList.contains(i)) {
filterIndexList.add(i);
}
}
}
}
list.clear();
if (!majorChange) {
Collections.sort(filterIndexList);
fireMontageChannelsRemoved(this, indices, primaryIndices);
fireMontageSampleFilterExclusionChanged(this, filterIndexList);
}
}
int size = montageChannels.size();
for (int i=0; i<size; i++) {
montageChannel = montageChannels.get(i);
LinkedList<Integer> indexList = new LinkedList<Integer>();
LinkedList<Integer> primaryIndexList = new LinkedList<Integer>();
if (montageChannel.hasReference(channel)) {
montageChannel.removeReference(channel);
indexList.add(i);
primaryIndexList.add(montageChannel.getPrimaryChannel().getChannel());
}
if (!indexList.isEmpty()) {
if (!majorChange) {
fireMontageReferenceChanged(this, indexList, primaryIndexList);
}
}
}
super.removeLastSourceChannel();
setMontageGenerator(null);
return channel;
}
/**
* Adds a given {@link MontageChannel montage channel} to necessary
* collections (montageChannels, montageChannelsByLabel,
* montageChannelsByPrimary).
* To montageChannels it is added at a given index.
* @param channel a montage channel to be added
* @param atIndex an index at which channel will be added to
* montageChannels list. If atIndex<0 then will be added
* at the end of the list
* @return an index at which channel was added to a montageChannels list
*/
protected int addMontageChannelInternal(MontageChannel channel, int atIndex) {
getMontageChannelsByLabel().put(channel.getLabel(), channel);
getMontageChannelsByPrimaryList(channel.getPrimaryChannel()).add(channel);
if (atIndex < 0) {
montageChannels.add(channel);
return montageChannels.size() - 1;
} else {
montageChannels.add(atIndex, channel);
return atIndex;
}
}
/**
* Creates a montage channel using a {@link SourceChannel source channel}
* of a given index as primaryChannel and puts it at selected index on
* a montageChannels list.
* @param sourceIndex index of a SourceChannel
* @param atIndex index at which channel will be added to the
* montageChannels list. If atIndex<0 then will be added at the end of
* the list.
* @return index at which channel was added to montageChannels list.
*/
public int addMontageChannel(int sourceIndex, int atIndex) {
int[] sourceIndices = new int[] { sourceIndex };
int[] indices = addMontageChannels(sourceIndices, atIndex);
return indices[0];
}
/**
* Creates a montage channel using a {@link SourceChannel source channel}
* of a given index as primaryChannel and puts it at the end
* montageChannels list.
* @param sourceIndex index of a SourceChannel
* @return index at which channel was added to montageChannels list.
*/
public int addMontageChannel(int sourceIndex) {
return addMontageChannel(sourceIndex, -1);
}
/**
* For each index on a sourceIndices list creates a
* {@link MontageChannel montage channel} with a
* {@link SourceChannel source channel} of this index as primaryChannel.
* Puts created montage channel at the end of montageChannels list.
* @param sourceIndices a list of indexes of SourceChannels
* @return a list of indexes of created montage channels on
* a montageChannels list
*/
public int[] addMontageChannels(int[] sourceIndices) {
return addMontageChannels(sourceIndices, -1);
}
/**
* Creates {@link MontageChannel montage channels} from
* {@link SourceChannel source channels} of <i>count</i> consecutive
* indexes starting from <i>fromSourceIndex</i>
* and puts them on a <i>montageChannels</i> list starting from
* <i>atIndex</i>.
* @param fromSourceIndex an index of a source channel from which adding
* new montage channels will be started
* @param count a number of montage channels to be added
* @param atIndex an index starting from which created montage channels
* are to be put. If atIndex<0 then they will be added at the end of
* the list
* @return a list of indexes of created montage channels on a montageChannels list
*/
public int[] addMontageChannels(int fromSourceIndex, int count, int atIndex) {
int[] sourceIndices = new int[count];
for (int i=0; i<count; i++) {
sourceIndices[i] = fromSourceIndex + i;
}
return addMontageChannels(sourceIndices, atIndex);
}
/**
* Creates {@link MontageChannel montage channels} from
* {@link SourceChannel source channel} of <i>count</i> consecutive
* indexes starting from <i>fromSourceIndex</i>
* and puts them at the end of <i>montageChannels</i> list.
* @param fromSourceIndex an index of a source channel from which adding
* new montage channels will be started
* @param count a number of montage channel to be added
* @return a list of indexes of created montage channels on a
* montageChannels list
*/
public int[] addMontageChannels(int fromSourceIndex, int count) {
return addMontageChannels(fromSourceIndex, count, -1);
}
/**
* For each index on a sourceIndices list creates
* {@link MontageChannel montage channels} with a
* {@link SourceChannel source channel} of this index as primaryChannel.
* Puts created montage channels on a montageChannels list starting from
* a given index.
* @param sourceIndices a list of indexes of source channels
* @param atIndex an index starting from which created montage channels
* are to be put. If atIndex<0 then will be added at the end of a list.
* @return a list of indexes of created montage channels on
* a montageChannels list
*/
public int[] addMontageChannels(int[] sourceIndices, int atIndex) {
int[] indices = new int[sourceIndices.length];
if (sourceIndices.length == 0) {
return indices;
}
SourceChannel channel;
MontageChannel montageChannel;
for (int i=0; i<sourceIndices.length; i++) {
channel = sourceChannels.get(sourceIndices[i]);
montageChannel = new MontageChannel(channel);
montageChannel.setLabel(getNewMontageChannelLabel(channel.getLabel()));
indices[i] = addMontageChannelInternal(montageChannel, (atIndex < 0 ? atIndex : atIndex+i));
}
if (!majorChange) {
fireMontageChannelsAdded(this, indices, sourceIndices);
setChanged(true);
}
setMontageGenerator(null);
return indices;
}
/**
* Adds a bipolar {@link MontageChannel montage channel} to a montage
* with a selected reference channel
* @param sourceIndex an index of a {@link SourceChannel source channel}
* @param atIndex an index at which channel will be added to a
* montageChannels list. If atIndex<0 then will be added at the
* end of a list.
* @param label a label of a new montage channel
* @param referenceChannel an index of a source channel to which
* montage channel should have a reference
* @return an index at which the channel was added to
* a montageChannels list.
*/
public int addBipolarMontageChannel(int sourceIndex, int atIndex, String label, int referenceChannel) {
SourceChannel channel = sourceChannels.get(sourceIndex);
MontageChannel montageChannel = new MontageChannel(channel);
montageChannel.setLabel(getNewMontageChannelLabel(label));
montageChannel.setReference(sourceChannels.get(referenceChannel), "-1");
int index = addMontageChannelInternal(montageChannel, atIndex);
if (!majorChange) {
int[] indices = new int[] { index };
int[] sourceIndices = new int[] { sourceIndex };
fireMontageChannelsAdded(this, indices, sourceIndices);
setChanged(true);
}
setMontageGenerator(null);
return index;
}
/**
* Adds a bipolar {@link MontageChannel montage channel} to a montage
* with a selected reference channel. Puts it at the end of
* the montageChannels list.
* @param sourceIndex an index of a {@link SourceChannel source channel}
* @param label a label of a new montage channel
* @param referenceChannel an index of a source channel to which
* montage channel should have a reference
* @return an index at which the channel was added to
* the montageChannels list.
*/
public int addBipolarMontageChannel(int sourceIndex, String label, int referenceChannel) {
return addBipolarMontageChannel(sourceIndex, -1, label, referenceChannel);
}
/**
* Removes a {@link MontageChannel montage channel} of specified index.
* @param index an index of a channel to be removed
* @return the removed montage channel
*/
public MontageChannel removeMontageChannel(int index) {
int[] indices = new int[] { index };
MontageChannel[] channels = removeMontageChannels(indices);
return channels[0];
}
/**
* Removes consecutive {@link MontageChannel montage channels} starting
* from a given index.
* @param fromIndex an index to start from
* @param count a number of channels to be removed
* @return an array of removed montage channels
*/
public MontageChannel[] removeMontageChannels(int fromIndex, int count) {
int[] indices = new int[count];
for (int i=0; i<count; i++) {
indices[i] = fromIndex + i;
}
return removeMontageChannels(indices);
}
/**
* Removes {@link MontageChannel montage channels} of specified indexes.
* @param indices a list of indexes of channels to be removed
* @return an array of removed montage channels
*/
public MontageChannel[] removeMontageChannels(int[] indices) {
MontageChannel[] channels = new MontageChannel[indices.length];
if (indices.length == 0) {
return channels;
}
int[] sourceIndices = new int[indices.length];
for (int i=0; i<indices.length; i++) {
channels[i] = montageChannels.get(indices[i]);
sourceIndices[i] = channels[i].getPrimaryChannel().getChannel();
getMontageChannelsByLabel().remove(channels[i].getLabel());
getMontageChannelsByPrimaryList(channels[i].getPrimaryChannel()).remove(channels[i]);
}
LinkedList<Integer> filterIndexList = new LinkedList<Integer>();
for (int i=0; i<indices.length; i++) {
montageChannels.remove(channels[i]);
}
Iterator<MontageSampleFilter> it = filters.iterator();
MontageSampleFilter filter;
while (it.hasNext()) {
filter = it.next();
for (int i=0; i<indices.length; i++) {
if (filter.removeExcludedChannel(channels[i])) {
if (!filterIndexList.contains(i)) {
filterIndexList.add(i);
}
}
}
}
if (!majorChange) {
Collections.sort(filterIndexList);
fireMontageChannelsRemoved(this, indices, sourceIndices);
fireMontageSampleFilterExclusionChanged(this, filterIndexList);
setChanged(true);
}
setMontageGenerator(null);
return channels;
}
/**
* Moves count consecutive {@link MontageChannel montage channels}
* on a montageChannels list starting from given index.
* @param fromIndex an index from which selecting montage channels
* to be moved starts
* @param count a number of consecutive MontageChannels to be moved
* @param delta a number of positions MontageChannels are to be moved.
* If > 0 channels are moved forward, if < 0 are moved backward.
* @return a number of positions MontageChannels were moved
*/
public int moveMontageChannelRange(int fromIndex, int count, int delta) {
if (delta == 0 || count == 0) {
return 0;
}
int possibleDelta;
int size = montageChannels.size();
if (delta > 0) {
possibleDelta = Math.min(delta, size - (fromIndex+count));
} else {
possibleDelta = Math.max(delta, -fromIndex);
}
if (possibleDelta == 0) {
return 0;
}
LinkedList<Integer> indexList = new LinkedList<Integer>();
LinkedList<Integer> primaryIndexList = new LinkedList<Integer>();
MontageChannel channel;
int i;
MontageChannel[] cache = new MontageChannel[count];
for (i=0; i<count; i++) {
cache[i] = montageChannels.get(fromIndex + i);
}
if (possibleDelta > 0) {
// rows moved down
for (i=0; i<possibleDelta; i++) {
channel = montageChannels.get(fromIndex + count + i);
montageChannels.set(fromIndex + i, channel);
indexList.add(fromIndex + i);
primaryIndexList.add(channel.getPrimaryChannel().getChannel());
}
} else if (possibleDelta < 0) {
// rows moved up
for (i=-1; i>=possibleDelta; i--) {
channel = montageChannels.get(fromIndex + i);
montageChannels.set(fromIndex + count + i, channel);
indexList.add(fromIndex + count + i);
primaryIndexList.add(channel.getPrimaryChannel().getChannel());
}
}
for (i=0; i<count; i++) {
montageChannels.set(fromIndex + possibleDelta + i, cache[i]);
indexList.add(fromIndex + possibleDelta + i);
primaryIndexList.add(cache[i].getPrimaryChannel().getChannel());
}
if (!majorChange) {
fireMontageStructureChanged(this);
setChanged(true);
}
setMontageGenerator(null);
return possibleDelta;
}
/**
* Returns if the montage is bipolar (has only bipolar references).
* @return true if the montage is bipolar, false otherwise
*/
public boolean isBipolar() {
for (MontageChannel channel : montageChannels) {
if (!channel.isBipolarReference()) {
return false;
}
}
return true;
}
/**
* Returns whether the montage is filtered.
* @return true if the montage is filtered, false otherwise
*/
public boolean isFiltered() {
if (!filteringEnabled) {
return false;
}
if (filters.isEmpty()) {
return false;
}
return true;
}
/**
* Checks whether a given montage channel is excluded from all filters.
* @param channel an index of montage channel to be checked
* @return true if a montage channel is excluded from all filters, false otherwise
*/
public boolean isExcludeAllFilters(int channel) {
return montageChannels.get(channel).isExcludeAllFilters();
}
/**
* Sets if a given {@link MontageChannel montage channel} should
* exclude all filters.
* @param channel an index of a montage channel for which
* a new value is to be set
* @param exclude true if all channels should be excluded,
* false otherwise
*/
public void setExcludeAllFilters(int channel, boolean exclude) {
MontageChannel montageChannel = montageChannels.get(channel);
boolean oldValue = montageChannel.isExcludeAllFilters();
if (oldValue != exclude) {
montageChannel.setExcludeAllFilters(exclude);
if (!majorChange) {
fireMontageSampleFiltersChanged(this);
setChanged(true);
}
}
}
/**
* Returns the number of filters for a montage.
* @return the number of filters for a montage
*/
public int getSampleFilterCount() {
return filters.size();
}
/**
* Returns the definition of a filter of a given index.
* @param index an index of a filter
* @return the definition of a filter
*/
public SampleFilterDefinition getSampleFilterAt(int index) {
return filters.get(index).getDefinition();
}
/**
* Adds a new filter to a montage.
* (Note: {@link TimeDomainSampleFilter TimeDomainSampleFilters} are
* added before {@link FFTSampleFilter FFTSampleFilters}).
* @param definition a definition of a filter to be added
* @return an index of added filter
*/
public int addSampleFilter(SampleFilterDefinition definition) {
MontageSampleFilter filter = new MontageSampleFilter(definition);
//time domain filters are added and thus processed before FFTSampleFilters
if (definition instanceof TimeDomainSampleFilter) {
int i = 0;
for (i = 0; i < filters.size(); i++) {
if (filters.get(i).getDefinition() instanceof FFTSampleFilter)
break;
}
filters.add(i, filter);
}
else
filters.add(filter);
int index = filters.indexOf(filter);
if (!majorChange) {
fireMontageSampleFilterAdded(this, new int[] {index});
setChanged(true);
}
return index;
}
/**
* Changes the definition of a given filter.
* @param index an index of a filter
* @param definition new definition to be set
*/
public void updateSampleFilter(int index, SampleFilterDefinition definition) {
MontageSampleFilter montageSampleFilter = filters.get(index);
montageSampleFilter.setDefinition(definition);
if (!majorChange) {
fireMontageSampleFilterChanged(this, new int[] { index });
setChanged(true);
}
}
/**
* Removes a filter from a montage.
* @param index an index of filter to be removed
* @return the definition of a removed filter
*/
public SampleFilterDefinition removeSampleFilter(int index) {
MontageSampleFilter removed = filters.remove(index);
if (removed == null) {
return null;
}
if (!majorChange) {
fireMontageSampleFilterRemoved(this, new int[] { index });
setChanged(true);
}
return removed.getDefinition();
}
/**
* Removes all filters from the montage.
*/
public void clearFilters() {
filters.clear();
if (!majorChange) {
fireMontageSampleFiltersChanged(this);
setChanged(true);
}
}
/**
* Checks if a given channel is excluded from a given filter.
* If a filter is not enabled it is excluded for all channels.
* @param filterIndex an index of a filter
* @param channelIndex an index of a channel
* @return true if a channel is excluded from a filter, false otherwise
*/
public boolean isFilteringExcluded(int filterIndex, int channelIndex) {
if (isExcludeAllFilters(channelIndex)) {
return true;
} else {
MontageSampleFilter filter = filters.get(filterIndex);
if (!filter.isEnabled() || filter.isChannelExcluded(montageChannels.get(channelIndex))) {
return true;
}
}
return false;
}
/**
* Creates an array of exclusions for a given filter.
* On position <i>i<\i> is an information if channel <i>i<\i>
* is excluded from a given filter.
* If filter is not enabled it is excluded for all channels.
* @param filterIndex an index of a filter
* @return created array
*/
public boolean[] getFilteringExclusionArray(int filterIndex) {
MontageSampleFilter filter = filters.get(filterIndex);
if (!filter.isEnabled()) {
boolean[] trueArray = new boolean[montageChannels.size()];
Arrays.fill(trueArray, true);
return trueArray;
}
boolean[] exclusionArray = filter.getExclusionArray(montageChannels);
for (int i=0; i<exclusionArray.length; i++) {
exclusionArray[i] |= isExcludeAllFilters(i);
}
return exclusionArray;
}
/**
* Checks if a filter is enabled (option to exclude all
* channels checked).
* @param filterIndex an index of a filter
* @return true if filter is enabled, false otherwise
*/
public boolean isFilterEnabled(int filterIndex) {
return filters.get(filterIndex).isEnabled();
}
/**
* Sets if a filter should be enabled (option to exclude all
* channels checked).
* @param filterIndex an index of a filter
* @param enabled the value to be set
*/
public void setFilterEnabled(int filterIndex, boolean enabled) {
MontageSampleFilter filter = filters.get(filterIndex);
boolean oldEnabled = filter.isEnabled();
if (oldEnabled != enabled) {
filter.setEnabled(enabled);
if (!majorChange) {
fireMontageSampleFilterExclusionChanged(this, new int[] { filterIndex });
setChanged(true);
}
}
}
/**
* Checks if a channel is excluded from a filter.
* DOESN'T include a situation when a filter is not enabled or
* a channel is excluded from all filters.
* @param filterIndex an index of a filter
* @param channelIndex an index of a channel
* @return true if a filter is excluded, false otherwise
*/
public boolean isFilterChannelExcluded(int filterIndex, int channelIndex) {
return filters.get(filterIndex).isChannelExcluded(montageChannels.get(channelIndex));
}
/**
* Creates an array of exclusions for a given filter.
* On position <i>i<\i> is an information if channel <i>i<\i>
* is excluded from a given filter.
* DOESN'T include a situation when a filter is not enabled or a channel
* is excluded from all filters.
* @param filterIndex an index of a filter
* @return created array
*/
public boolean[] getFilterExclusionArray(int filterIndex) {
return filters.get(filterIndex).getExclusionArray(montageChannels);
}
/**
* Sets if a given channel should be excluded from a given filter.
* @param filterIndex an index of a filter
* @param channelIndex an index of a channel
* @param excluded the value to be set (true if should be excluded,
* false otherwise)
*/
public void setFilterChannelExcluded(int filterIndex, int channelIndex, boolean excluded) {
boolean done;
if (excluded) {
done = filters.get(filterIndex).addExcludedChannel(montageChannels.get(channelIndex));
} else {
done = filters.get(filterIndex).removeExcludedChannel(montageChannels.get(channelIndex));
}
if (done) {
if (!majorChange) {
fireMontageSampleFilterExclusionChanged(this, new int[] { filterIndex });
setChanged(true);
}
}
}
/**
* Clears exclusions for a given filter.
* DOESN'T include a situation when a filter is not enabled or
* a channel is excluded from all filters.
* @param filterIndex an index of a filter
*/
public void clearFilterExclusion(int filterIndex) {
boolean done = filters.get(filterIndex).clearExclusion();
if (done) {
if (!majorChange) {
fireMontageSampleFilterExclusionChanged(this, new int[] { filterIndex });
setChanged(true);
}
}
}
/**
* Adds a MontageListener to a montage.
* @param l a MontageListener to be added
*/
public void addMontageListener(MontageListener l) {
listenerList.add(MontageListener.class, l);
}
/**
* Removes a MontageListener from a montage.
* @param l a MontageListener to be removed
*/
public void removeMontageListener(MontageListener l) {
listenerList.remove(MontageListener.class, l);
}
/**
* Adds a MontageSampleFilterListener to a montage.
* @param l a MontageSampleFilterListener to be added
*/
public void addMontageSampleFilterListener(MontageSampleFilterListener l) {
listenerList.add(MontageSampleFilterListener.class, l);
}
/**
* Removes a MontageSampleFilterListener from a montage.
* @param l a MontageSampleFilterListener to be removed
*/
public void removeMontageSampleFilterListener(MontageSampleFilterListener l) {
listenerList.remove(MontageSampleFilterListener.class, l);
}
/**
* Fires all MontageListeners that a montage structure has changed.
* @param source a montage that has changed
*/
protected void fireMontageStructureChanged(Object source) {
Object[] listeners = listenerList.getListenerList();
MontageEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageListener.class) {
if (e == null) {
e = new MontageEvent(source, null, null);
}
((MontageListener)listeners[i+1]).montageStructureChanged(e);
}
}
}
/**
* Fires all MontageListeners that channels has been added.
* @param source a montage that has changed
* @param channels an array with indexes of added montage channels
* @param primaryChannels an array with indexes of SourceChannels
* that were added
*/
protected void fireMontageChannelsAdded(Object source, int[] channels, int[] primaryChannels) {
Object[] listeners = listenerList.getListenerList();
MontageEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageListener.class) {
if (e == null) {
e = new MontageEvent(source, channels, primaryChannels);
}
((MontageListener)listeners[i+1]).montageChannelsAdded(e);
}
}
}
/**
* Fires all MontageListeners that channels has been removed.
* @param source a montage that has changed
* @param channels an array with indexes of removed channels
* @param primaryChannels an array with indexes of SourceChannels
* that were removed
*/
protected void fireMontageChannelsRemoved(Object source, int[] channels, int[] primaryChannels) {
Object[] listeners = listenerList.getListenerList();
MontageEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageListener.class) {
if (e == null) {
e = new MontageEvent(source, channels, primaryChannels);
}
((MontageListener)listeners[i+1]).montageChannelsRemoved(e);
}
}
}
/**
* Creates an array of int from LinkedList of Integers.
* @param list a LinkedList of Integers
* @return created array
*/
private int[] toArray(LinkedList<Integer> list) {
int i = 0;
int[] indices = new int[list.size()];
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
indices[i] = it.next();
i++;
}
return indices;
}
/**
* Fires all MontageListeners that channels has been changed.
* @param source a montage that has changed
* @param indexList a list with indexes of changed montage channels
* @param primaryIndexList a list with indexes of SourceChannels that
* were changed
*/
protected void fireMontageChannelsChanged(Object source, LinkedList<Integer> indexList, LinkedList<Integer> primaryIndexList) {
fireMontageChannelsChanged(source, toArray(indexList), toArray(primaryIndexList));
}
/**
* Fires all MontageListeners that channels has been changed.
* @param source a montage that has changed
* @param channels an array with indexes of changed montage channels
* @param primaryChannels an array with indexes of SourceChannels that
* were changed
*/
protected void fireMontageChannelsChanged(Object source, int[] channels, int[] primaryChannels) {
Object[] listeners = listenerList.getListenerList();
MontageEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageListener.class) {
if (e == null) {
e = new MontageEvent(source, channels, primaryChannels);
}
((MontageListener)listeners[i+1]).montageChannelsChanged(e);
}
}
}
/**
* Fires all MontageListeners that reference between pairs montage
* channel - source channel has been changed.
* @param source a montage that has changed
* @param indexList a list with indexes of montage channels with
* reference changed
* @param primaryIndexList a list with indexes of SourceChannels to
* which references changed
*/
protected void fireMontageReferenceChanged(Object source, LinkedList<Integer> indexList, LinkedList<Integer> primaryIndexList) {
fireMontageReferenceChanged(source, toArray(indexList), toArray(primaryIndexList));
}
/**
* Fires all MontageListeners that reference between pairs montage
* channel - source channel has been changed.
* @param source a montage that has changed
* @param channels an array with indexes of montage channels with
* reference changed
* @param primaryChannels array with indexes of SourceChannels to which
* references changed
*/
protected void fireMontageReferenceChanged(Object source, int[] channels, int[] primaryChannels) {
Object[] listeners = listenerList.getListenerList();
MontageEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageListener.class) {
if (e == null) {
e = new MontageEvent(source, channels, primaryChannels);
}
((MontageListener)listeners[i+1]).montageReferenceChanged(e);
}
}
}
/**
* Fires all MontageListeners that SampleFilters were added.
* @param source a montage that has changed
* @param indices an array of indexes of added filters
*/
protected void fireMontageSampleFilterAdded(Object source, int[] indices) {
Object[] listeners = listenerList.getListenerList();
MontageSampleFilterEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageSampleFilterListener.class) {
if (e == null) {
e = new MontageSampleFilterEvent(source, indices);
}
((MontageSampleFilterListener)listeners[i+1]).filterAdded(e);
}
}
}
/**
* Fires all MontageListeners that SampleFilters were changed.
* @param source a montage that has changed
* @param indices an array of indexes of changed filters
*/
protected void fireMontageSampleFilterChanged(Object source, int[] indices) {
Object[] listeners = listenerList.getListenerList();
MontageSampleFilterEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageSampleFilterListener.class) {
if (e == null) {
e = new MontageSampleFilterEvent(source, indices);
}
((MontageSampleFilterListener)listeners[i+1]).filterChanged(e);
}
}
}
/**
* Fires all MontageListeners that SampleFilters were removed.
* @param source montage that has changed
* @param indices array of indexes of removed filters
*/
protected void fireMontageSampleFilterRemoved(Object source, int[] indices) {
Object[] listeners = listenerList.getListenerList();
MontageSampleFilterEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageSampleFilterListener.class) {
if (e == null) {
e = new MontageSampleFilterEvent(source, indices);
}
((MontageSampleFilterListener)listeners[i+1]).filterRemoved(e);
}
}
}
/**
* Fires all MontageListeners that exclusions for SampleFilters were
* changed.
* @param source a montage that has changed
* @param indexList a list of indexes of filters for which exclusions
* has changed
*/
protected void fireMontageSampleFilterExclusionChanged(Object source, LinkedList<Integer> indexList) {
fireMontageSampleFilterExclusionChanged(source, toArray(indexList));
}
/**
* Fires all MontageListeners that exclusions for SampleFilters were
* changed.
* @param source a montage that has changed
* @param indices an array of indexes of filters for which exclusions
* has changed
*/
protected void fireMontageSampleFilterExclusionChanged(Object source, int[] indices) {
Object[] listeners = listenerList.getListenerList();
MontageSampleFilterEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageSampleFilterListener.class) {
if (e == null) {
e = new MontageSampleFilterEvent(source, indices);
}
((MontageSampleFilterListener)listeners[i+1]).filterExclusionChanged(e);
}
}
}
/**
* Fires all MontageListeners that all SampleFilters were changed.
* @param source a montage that has changed
*/
protected void fireMontageSampleFiltersChanged(Object source) {
Object[] listeners = listenerList.getListenerList();
MontageSampleFilterEvent e = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MontageSampleFilterListener.class) {
if (e == null) {
e = new MontageSampleFilterEvent(source);
}
((MontageSampleFilterListener)listeners[i+1]).filtersChanged(e);
}
}
}
}