content: package aliview.sequencelist;
  
  import java.awt.Point;
  import java.awt.Rectangle;
  import java.io.IOException;
  import java.io.Serializable;
  import java.util.ArrayList;
  import java.util.BitSet;
  import java.util.EventListener;
  import java.util.List;
  
  import javax.swing.DefaultListSelectionModel;
  import javax.swing.ListSelectionModel;
  import javax.swing.event.EventListenerList;
  import javax.swing.event.ListSelectionEvent;
  import javax.swing.event.ListSelectionListener;
  
  import jebl.evolution.sequences.Sequences;
  
  import org.apache.commons.lang.ArrayUtils;
  import org.apache.commons.lang.StringUtils;
  import org.apache.log4j.Logger;
  
  import aliview.AliView;
  import aliview.alignment.AlignmentMeta;
  import aliview.sequences.Sequence;
  import aliview.sequencelist.Interval;
  import aliview.utils.Utils;
  
  /**
   * 
   * This model is delegating to the sequences themself to keep track of selection
   * 
   * 
   */
  
  public class AlignmentSelectionModel{
  
  	private static final Logger logger = Logger.getLogger(AlignmentSelectionModel.class);
  	private static final String LF = System.getProperty("line.separator");
  	private AlignmentListModel sequences;
  	protected EventListenerList listenerList = new EventListenerList();
  	private Rectangle tempSelectionRect;
  	private Rectangle tempSelectionMaxRect;
  	private SequenceListSelectionModel sequenceListSelectionModel;
  
  	public AlignmentSelectionModel(AlignmentListModel sequenceListModel) {
  		this.sequences = sequenceListModel;
  		this.sequenceListSelectionModel = new SequenceListSelectionModel(this);
  	}
  
  
  	public SequenceListSelectionModel getSequenceListSelectionModel() {
  		return sequenceListSelectionModel;
  	}
  
  
  	public ArrayList<Integer> getIndicesOfSequencesWithSelection() {
  		ArrayList<Integer> indices = new ArrayList<Integer>();
  		for(int n = 0; n < sequences.size(); n++){
  			if(sequences.get(n).hasSelection()){
  				indices.add(new Integer(n));
  			}
  		}
  		return indices;
  	}
  
  	public ArrayList<Integer> getIndicesOfSequencesWithAllSelected() {
  		ArrayList<Integer> indices = new ArrayList<Integer>();
  		for(int n = 0; n < sequences.size(); n++){
  			if(sequences.get(n).isAllSelected()){
  				indices.add(new Integer(n));
  			}
  		}
  		return indices;
  	}
  
  	public boolean isBaseSelected(int x, int y) {
  		//logger.info("isBaseSel" + sequences.get(y));
  		boolean isSel = sequences.get(y).isBaseSelected(x);
  		//		if(isSel){ logger.info("isSel" + sequences.get(y));};
  		return sequences.get(y).isBaseSelected(x);
  	}
  
  
  
  	public void selectSequenceWithIndex(int index){
  		setSequenceSelection(index, index);
  	}
  
  	public void selectSequencesWithIndex(List<Integer> listVals){
  		Integer[] array = listVals.toArray(new Integer[listVals.size()]);	
  		int[] intVals = ArrayUtils.toPrimitive(array, 0);
  		selectSequencesWithIndex(intVals);
  	}
  
  	public void selectSequencesWithIndex(int[] selectedIndex){
  		List<Sequence> seqs = new ArrayList<Sequence>(selectedIndex.length);
  		for(int index: selectedIndex){
  			seqs.add(sequences.get(index));
  		}	
  		changeSelection(seqs, true);
  	}
  
  	public void setSelectionAt(int xPos, int yPos) {
  		setSelectionAt(xPos, yPos, false);
  	}
  
  	public void setSelectionAt(int xPos, int yPos, boolean clearFirst) {
  		//delegateLSM.setAnchorSelectionIndex(yPos);
  		//delegateLSM.setLeadSelectionIndex(yPos);
  		changeSelection(xPos, yPos, xPos, yPos, clearFirst);
  	}
  
  
  	private void changeSelection(int x1, int y1, int x2, int y2, boolean clearFirst){
  
  		Rectangle newRect = new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
  
  		logger.info("newRect" + newRect);
  
  		// Get current selection so we can fire a correct bounding box
  		Rectangle oldSelectRect = getSelectionBounds();
  
  		// value is adjusting true
  
  		for(int n = 0; n < sequences.size(); n++){
  
  			if(n>= newRect.getMinY() && n <= newRect.getMaxY()){
  				sequences.get(n).setSelection(newRect.x, newRect.x + newRect.width, clearFirst);
  			}else{
  				sequences.get(n).clearAllSelection();
  			}
  		}
  
  		// affected area is old selection plus new
  		if(clearFirst && oldSelectRect != null){
  			logger.info("newRect" + newRect);
  			logger.info("oldRect" + oldSelectRect);
  			if(Utils.hasSameBounds(newRect, oldSelectRect)){	
  				// do nothing
  			}else{
  				Rectangle both = Utils.addRects(oldSelectRect, newRect);
  				fireSelectionChanged(both, false);
  			}
  		}
  		else{
  			fireSelectionChanged(newRect, false);
  		}
  	}
  
  	public void setSequenceSelection(int index0, int index1) {
  		changeSelection(index0, index1, true);
  	}
  
  	public void addSequenceSelection(int index0, int index1) {
  		changeSelection(index0, index1, false);
  	}
  
  	public void removeSequenceSelection(int index0, int index1) {
  		// set value is adjusting true
  
  		int minIndex = Math.min(index0, index1);
  		int maxIndex = Math.max(index0, index1);
  
  		for(int n = 0; n < sequences.size(); n++){
  
  			if(n>= minIndex && n<= maxIndex){
  				sequences.get(n).clearAllSelection();
  			}else{
  				// nothing
  			}
  		}
  
  		// fire all because on insert and delete indexes might change
  		fireSelectionChanged(0, sequences.size());
  
  	}
  
  	public void setSequenceSelection(List<Sequence> moreSeqs) {
  		changeSelection(moreSeqs, true);
  
  	}
  
  	private void changeSelection(List<Sequence> toSelect, boolean clearFirst){
  		Rectangle oldSelect = getSelectionBounds();
  		logger.info("toSelect.size()" + toSelect.size());
  		for(Sequence seq: sequences){
  
  			if(toSelect.contains(seq)){
  				logger.debug("select" + seq);
  				seq.selectAllBases();
  			}
  			else if(clearFirst){
  				seq.clearAllSelection();
  			}
  
  		}
  		Rectangle newSelect = getSelectionBounds();
  		logger.info("newSelect" + newSelect);		
  		Rectangle addedSelection = Utils.addRects(oldSelect, newSelect);
  
  		if(addedSelection != null){
  			fireSelectionChanged(addedSelection, false);
  		}
  	}
  
  
  	private void changeSelection(int index0, int index1, boolean clearFirst){
  
  		// set value is adjusting true
  		int minIndex = Math.min(index0, index1);
  		int maxIndex = Math.max(index0, index1);
  
  		for(int n = 0; n < sequences.size(); n++){
  
  			if(n>= minIndex && n<= maxIndex){
  				sequences.get(n).selectAllBases();
  			}else{
  				if(clearFirst){
  					sequences.get(n).clearAllSelection();
  				}
  			}
  		}
  
  		// Update all
  		fireSelectionChanged(0, sequences.size());
  
  		// set value is adjusting false
  		//		if(clearFirst || updateAll){
  		//			fireSelectionChanged(0, sequences.size());
  		//		}else{
  		//			fireSelectionChanged(minIndex, maxIndex);
  		//		}
  	}
  
  
  	public long getSelectionSize(){
  		long size = 0;
  		for(Sequence sequence : this.sequences){
  			size += sequence.countSelectedPositions(0, sequence.getLength());
  		}
  		return size;
  	}
  
  	public Rectangle getSelectionBounds(){
  		if(! hasSelection()){
  			return null;
  		}
  		// TODO this could be changed if non rectangular selections
  		Rectangle bounds = new Rectangle(getFirstSelectedPos());
  		bounds.add(getLastSelectedPos());
  		return bounds;
  	}
  
  	public List<Sequence> getSelectedSequences() {
  		ArrayList<Sequence> selection = new ArrayList<Sequence>();
  		for(Sequence sequence : sequences){
  			if(sequence.hasSelection()){
  				selection.add(sequence);
  			}
  		}
  		return selection;
  	}
  
  	public List<Sequence> getUnSelectedSequences() {
  		ArrayList<Sequence> selection = new ArrayList<Sequence>();
  		for(Sequence sequence : sequences){
  			if(! sequence.hasSelection()){
  				selection.add(sequence);
  			}
  		}
  		return selection;
  	}
  
  
  
  
  
  
  	public void selectBases(Sequence seq, Interval foundPos) {
  		seq.setSelection(foundPos.startPos, foundPos.endPos, false);
  		fireSelectionChanged(seq, true);
  	}
  
  
  
  
  
  
  	public void selectAllBasesUntilGapInThisSequence(Sequence sequence, int x){
  		sequence.selectAllBasesUntilGap(x);
  		fireSelectionChanged(sequence, false);
  	}
  
  
  
  
  
  	public void selectSequences(List<Sequence> seqs) {
  		changeSelection(seqs, true);
  	}
  
  	public String getSelectionAsNucleotides() {
  		StringBuilder selection = new StringBuilder();
  		for(Sequence sequence : sequences){
  			if(sequence.getSelectedBasesAsString() != null && sequence.getSelectedBasesAsString().length() > 0){
  				selection.append(sequence.getSelectedBasesAsString());
  				selection.append(LF);
  			}
  		}
  		return selection.toString();
  	}
  
  	public String getFirstSelectedName() {
  		String name = null;
  		if(getFirstSelected() != null){
  			name = getFirstSelected().getName();
  		}
  		return name;
  	}
  
  	public List<Sequence> setFirstSelectedName(String newName) {
  		List<Sequence> editedSequences = new ArrayList<Sequence>();
  		if(newName == null){
  			return editedSequences;
  		}
  		if(getFirstSelected() != null){
  			editedSequences.add(getFirstSelected().getCopy());
  			getFirstSelected().setName(newName);
  		}
  		return editedSequences;
  	}
  
  	public Sequence getFirstSelected() {
  		for(int n = 0; n < sequences.size(); n++){
  			if(sequences.get(n).hasSelection()){
  				return sequences.get(n);
  			}
  		}
  		return null;
  	}
  
  	public boolean hasSelection() {
  		long startTime = System.currentTimeMillis();
  		for(Sequence sequence : sequences){
  			if(sequence.hasSelection()){
  				return true;
  			}
  		}
  		long endTime = System.currentTimeMillis();
  		logger.info("hasSelection false " + (endTime - startTime) + " milliseconds");
  		return false;
  	}
  
  	public void selectAll() {
  		for(Sequence seq: sequences){
  			seq.selectAllBases();
  		}
  		fireSelectionChangedAll();
  	}
  
  	public void selectionExtendRight(){
  		if(!hasSelection()){
  			return;
  		}
  		Rectangle oldSelect = getSelectionBounds();
  		for(Sequence seq: sequences){
  			seq.selectionExtendRight();
  		}
  		Rectangle newSelect = getSelectionBounds();
  		newSelect.add(oldSelect);
  		fireSelectionChanged(newSelect, false);
  	}
  
  	public void selectionExtendLeft() {
  		if(!hasSelection()){
  			return;
  		}
  		
  		Rectangle oldSelect = getSelectionBounds();
  		for(Sequence seq: sequences){
  			seq.selectionExtendLeft();
  		}
  		Rectangle newSelect = getSelectionBounds();
  		newSelect.add(oldSelect);
  		fireSelectionChanged(newSelect, false);
  	}
  
  	public void selectionExtendDown() {	
  		if(!hasSelection()){
  			return;
  		}
  		
  		Rectangle oldSelect = getSelectionBounds();
  
  		// start from top and loop till last but one
  		for(int n = 0; n < sequences.size() - 1; n++){
  			Sequence seq = sequences.get(n);
  			if(seq.hasSelection()){
  				int[] selected = seq.getSelectedPositions();
  				for(int index: selected){
  					sequences.get(n+1).setSelection(index,index, false);
  				}
  			}
  		}
  		Rectangle newSelect = getSelectionBounds();
  		newSelect.add(oldSelect);
  		fireSelectionChanged(newSelect, false);
  	}
  	
  	public void selectionExtendTop() {
  		if(!hasSelection()){
  			return;
  		}
  		
  		Rectangle oldSelect = getSelectionBounds();
  
  		// start bottom and loop till top but one
  		for(int n = sequences.size() - 1; n > 0; n--){
  			Sequence seq = sequences.get(n);
  			if(seq.hasSelection()){
  				int[] selected = seq.getSelectedPositions();
  				for(int index: selected){
  					sequences.get(n-1).setSelection(index,index, false);
  				}
  			}
  		}
  		Rectangle newSelect = getSelectionBounds();
  		newSelect.add(oldSelect);
  		fireSelectionChanged(newSelect, false);
  	}
  
  
  	public void invertSelection() {
  		for(Sequence seq: sequences){
  			seq.invertSelection();
  		}
  		fireSelectionChangedAll();
  	}
  
  	public void copySelectionFromInto(int indexFrom, int indexTo) {
  		Sequence seqFrom = sequences.get(indexFrom);
  		Sequence seqTo = sequences.get(indexTo);
  
  		for(int x = 0; x < seqFrom.getLength() || x < seqTo.getLength(); x++){
  			if(seqFrom.isBaseSelected(x)){
  				seqTo.setSelectionAt(x);
  			}
  			else{
  				seqTo.clearSelectionAt(x);
  			}
  		}
  
  		fireSelectionChanged(indexFrom, indexTo, false);
  
  	}
  
  	public void selectColumn(int columnIndex) {
  		for(Sequence seq: sequences){
  			seq.setSelectionAt(columnIndex);
  		}
  		fireSelectionChanged(new Rectangle(columnIndex,0,columnIndex,sequences.size()), false);
  	}
  
  	public void selectColumns(List<Integer> columns){
  		int maxIndex = 0;
  		int minIndex = sequences.getLongestSequenceLength();
  		for(Integer col: columns){
  			maxIndex = Math.max(maxIndex, col.intValue());
  			minIndex = Math.min(minIndex, col.intValue());
  			for(Sequence seq: sequences){
  				seq.setSelectionAt(col.intValue());
  			}
  		}
  		fireSelectionChanged(new Rectangle(minIndex,0,maxIndex,sequences.size()), false);
  	}
  
  	public void clearColumnSelection(int columnIndex) {
  		for(Sequence seq: sequences){
  			seq.clearSelectionAt(columnIndex);
  		}
  		fireSelectionChanged(new Rectangle(columnIndex,0,0,sequences.size()), false);	
  	}
  
  	public void copySelectionFromPosX1toX2(int x1, int x2) {
  		for(Sequence seq: sequences){
  			if(seq.isBaseSelected(x1)){
  				seq.setSelectionAt(x2);
  			}
  			else{
  				seq.clearSelectionAt(x2);
  			}
  		}
  		fireSelectionChanged(new Rectangle(x1,0,x2,sequences.size()), false);
  	}
  
  	public Point getFirstSelectedPos() {
  		int n = getFirstSelectedSequenceIndex();
  		if(n != -1){
  			return new Point(sequences.get(n).getFirstSelectedPosition(), n);
  		}else{
  			return null;
  		}
  	}
  
  	public int getFirstSelectedSequenceIndex() {
  		for(int n = 0; n < sequences.size(); n++){
  			if(sequences.get(n).hasSelection()){
  				return n;
  			}
  		}
  		return -1;
  	}
  
  	public int getLastSelectedSequenceIndex() {
  		for(int n = sequences.size() - 1; n >= 0; n--){
  			if(sequences.get(n).hasSelection()){
  				return n;
  			}
  		}
  		return -1;
  	}
  
  	public Point getLastSelectedPos() {
  		int n = getLastSelectedSequenceIndex();
  		if(n != -1){
  			return new Point(sequences.get(n).getLastSelectedPosition(), n);
  		}else{
  			return null;
  		}
  	}
  
  	public Point getFirstSelectedUngapedPos() {
  		for(int n = 0; n < sequences.size(); n++){
  			if(sequences.get(n).hasSelection()){
  				Sequence firstSelected = sequences.get(n);
  				int position = firstSelected.getFirstSelectedPosition();
  				int ungaped = firstSelected.getUngapedPos(position);
  				return new Point(ungaped, n);
  			}		
  		}
  		return null;		
  	}
  
  
  	public void setSelectionWithin(Rectangle bounds) {
  		changeSelection(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height, true);
  	}
  
  	public boolean hasFullySelectedSequences() {
  		for(Sequence seq: sequences){
  			if(seq.isAllSelected()){
  				return true;
  			}
  		}
  		return false;
  	}
  
  	public int getSelectedColumnCount() {
  		BitSet colSelect = new BitSet();
  		for(Sequence seq: sequences){
  			if(seq.hasSelection()){
  				int[] allSelected = seq.getSelectedPositions();
  				for(int nextInt: allSelected){
  					colSelect.set(nextInt);
  				}
  			}
  		}
  		return colSelect.cardinality();
  	}
  
  	public int getSelectedSequencesCount() {
  		int count = 0;
  		for(Sequence seq: sequences){
  			if(seq.hasSelection()){
  				count ++;
  			}
  		}
  		return count;
  	}
  
  
  
  	public String getSelectionNames() {
  		String names = "";
  		for(Sequence seq: sequences){
  			if(seq.hasSelection()){
  				names += seq.getName() + LF;
  			}
  		}
  		// remove last LF
  		if(names.length() > 0){
  			names = StringUtils.removeEnd(names, LF);
  		}
  
  		return names;
  	}
  
  	public int getFirstSelectedWholeColumn() {
  		Point pos = getFirstSelectedPos();
  		if(pos == null){
  			return -1;
  		}
  		else{
  			for(Sequence seq: sequences){
  				// seq has to be long enough
  				if(seq.getLength() > pos.x && !seq.hasSelection()){
  					return -1;
  				}
  			}
  			return pos.x;
  		}	
  	}
  
  	public int getLastSelectedWholeColumn() {
  		Point pos = getLastSelectedPos();
  		if(pos == null){
  			return -1;
  		}
  		else{
  			for(Sequence seq: sequences){
  				// seq has to be long enough
  				if(seq.getLength() > pos.x && !seq.hasSelection()){
  					return -1;
  				}
  			}
  			return pos.x;
  		}	
  	}
  
  
  
  	public void clearAllSelectionInSequenceWithIndex(int index) {
  		sequences.get(index).clearAllSelection();
  		fireSelectionChanged(index, index);
  	}
  
  	public void clearSequenceSelection() {
  
  		Rectangle oldSelectRectangle = getSelectionBounds();
  		for(Sequence seq: sequences){
  			seq.clearAllSelection();
  		}
  		if(oldSelectRectangle != null){
  			fireSelectionChanged(oldSelectRectangle, false);
  		}
  	}
  
  
  
  	/** {@inheritDoc} */
  	public void addAlignmentSelectionListener(AlignmentSelectionListener l) {
  		listenerList.add(AlignmentSelectionListener.class, l);
  	}
  
  	/** {@inheritDoc} */
  	public void removeSequenceListSelectionListener(AlignmentSelectionListener l) {
  		listenerList.remove(AlignmentSelectionListener.class, l);
  	}
  
  	/**
  	 * Returns an array of all the list selection listeners
  	 * registered on this <code>DefaultListSelectionModel</code>.
  	 *
  	 * @return all of this model's <code>ListSelectionListener</code>s
  	 *         or an empty
  	 *         array if no list selection listeners are currently registered
  	 *
  	 * @see #addListSelectionListener
  	 * @see #removeListSelectionListener
  	 *
  	 * @since 1.4
  	 */
  	public AlignmentSelectionListener[] getAlignmentSelectionListeners() {
  		return listenerList.getListeners(AlignmentSelectionListener.class);
  	}
  
  
  	/**
  	 * Notifies <code>ListSelectionListeners</code> that the value
  	 * of the selection, in the closed interval <code>firstIndex</code>,
  	 * <code>lastIndex</code>, has changed.
  	 */
  	protected void fireSelectionChanged(int firstIndex, int lastIndex) {
  		fireSelectionChanged(firstIndex, lastIndex, getValueIsAdjusting());
  	}
  
  	protected void fireSelectionChangedAll() {
  		fireSelectionChanged(0, sequences.size(), getValueIsAdjusting());
  	}
  
  	private boolean getValueIsAdjusting() {
  		// TODO Auto-generated method stub
  		return false;
  	}
  
  	/**
  	 * @param firstIndex the first index in the interval
  	 * @param lastIndex the last index in the interval
  	 * @param isAdjusting true if this is the final change in a series of
  	 *          adjustments
  	 * @see EventListenerList
  	 */
  	protected void fireSelectionChanged(int index0, int index1, boolean isAdjusting)
  	{
  		Rectangle rect = new Rectangle(0, Math.min(index0, index1), sequences.getLongestSequenceLength(), Math.abs(index0 - index1));
  		fireSelectionChanged(rect, isAdjusting);
  	}
  
  
  	private void fireSelectionChanged(Sequence sequence, boolean isAdjusting) {
  		int index = sequences.indexOf(sequence);
  		fireSelectionChanged(index, index, isAdjusting);
  
  	}
  
  	/*
      private void fireSelectionChanged(int x1, int y1, int x2, int y2, boolean isAdjusting) {
  	 */  	
  
  	private void fireSelectionChanged(Rectangle rect, boolean isAdjusting) {
  		logger.info("fire Selection changed + rect" + rect);
  		Object[] listeners = listenerList.getListenerList();
  		AlignmentSelectionEvent e = null;
  
  		for (int i = listeners.length - 2; i >= 0; i -= 2) {
  			if (listeners[i] == AlignmentSelectionListener.class) {
  				if (e == null) {
  					e = new AlignmentSelectionEvent(this, rect, isAdjusting);
  				}
  				((AlignmentSelectionListener)listeners[i+1]).selectionChanged(e);
  			}
  		}
  
  		// Also let ListView know
  		// delegateLSM.fireValueChanged(rect.y, rect.y + rect.height, isAdjusting);
  
  
  		if(AliView.getActiveWindow() != null){
  			logger.info("Time from last endTim " + (System.currentTimeMillis() - AliView.getActiveWindow().getLastPaneEndTime()) + " milliseconds");
  		}
  
  	}
  
  	/**
  	 * Returns an array of all the objects currently registered as
  	 * <code><em>Foo</em>Listener</code>s
  	 * upon this model.
  	 * <code><em>Foo</em>Listener</code>s
  	 * are registered using the <code>add<em>Foo</em>Listener</code> method.
  	 * <p>
  	 * You can specify the <code>listenerType</code> argument
  	 * with a class literal, such as <code><em>Foo</em>Listener.class</code>.
  	 * For example, you can query a <code>DefaultListSelectionModel</code>
  	 * instance <code>m</code>
  	 * for its list selection listeners
  	 * with the following code:
  	 *
  	 * <pre>ListSelectionListener[] lsls = (ListSelectionListener[])(m.getListeners(ListSelectionListener.class));</pre>
  	 *
  	 * If no such listeners exist,
  	 * this method returns an empty array.
  	 *
  	 * @param listenerType  the type of listeners requested;
  	 *          this parameter should specify an interface
  	 *          that descends from <code>java.util.EventListener</code>
  	 * @return an array of all objects registered as
  	 *          <code><em>Foo</em>Listener</code>s
  	 *          on this model,
  	 *          or an empty array if no such
  	 *          listeners have been added
  	 * @exception ClassCastException if <code>listenerType</code> doesn't
  	 *          specify a class or interface that implements
  	 *          <code>java.util.EventListener</code>
  	 *
  	 * @see #getListSelectionListeners
  	 *
  	 * @since 1.3
  	 */
  	public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  		return listenerList.getListeners(listenerType);
  	}
  
  	public void setTempSelection(Rectangle newSelectRect){
  		if(tempSelectionRect != null && tempSelectionRect.equals(newSelectRect)){
  			// old selection is the same - do nothing
  		}
  
  		if(tempSelectionRect == null){
  			tempSelectionRect = newSelectRect;
  			tempSelectionMaxRect = tempSelectionRect;
  		}
  
  		else{
  			tempSelectionRect = newSelectRect;
  			tempSelectionMaxRect.add(tempSelectionRect);
  			fireSelectionChanged(tempSelectionMaxRect, false);
  		}
  
  	}
  
  	public Rectangle getTempSelection() {
  		return tempSelectionRect;
  	}
  
  	public void clearTempSelection() {
  		this.tempSelectionRect = null;
  	}
  
  	public boolean isSequenceAtLeastPartlyAffectedByTempSelection(int index){
  		if(tempSelectionRect == null){
  			return false;
  		}
  		if(index >= tempSelectionRect.getMinY() && index <= tempSelectionRect.getMaxY()){
  			return true;
  		}
  		else{
  			return false;
  		}
  	}
  
  	public boolean isSequenceAtLeastPartlySelected(int index) {
  		if(! sequences.rangeCheck(0, index)){
  			return false;
  		}
  		if(isSequenceAtLeastPartlyAffectedByTempSelection(index)){
  			return true;
  		}
  		return sequences.get(index).hasSelection();
  	}
  
  	public void translateSelection(AlignmentMeta aliMeta) {
  		for(Sequence seq: sequences){
  			if(seq.hasSelection()){
  				if(! seq.isAllSelected()){
  					int[] selection = seq.getSelectedPositions();
  					int[] translated = aliMeta.translatePositions(selection);
  					seq.clearAllSelection();
  					for(int pos: translated){
  						seq.setSelectionAt(pos);
  					}
  				}
  			}
  		}
  		fireSelectionChangedAll();
  	}
  
  	public void reTranslateSelection(AlignmentMeta aliMeta) {
  		for(Sequence seq: sequences){
  			if(seq.hasSelection()){
  				if(! seq.isAllSelected()){
  					int[] selection = seq.getSelectedPositions();
  					int[] translated = aliMeta.reTranslatePositions(selection);
  					seq.clearAllSelection();
  					for(int pos: translated){
  						seq.setSelectionAt(pos);
  					}
  				}
  			}
  		}
  		fireSelectionChangedAll();
  
  	}
  }
  